Please dust off and fire up your Apple1 hardware and try to get a CC95 compiled "Hello, World!" program to work.
It's been my experience that CC95 programs work with the various emulators out there (it works on POM1 and MESS), but doesn't work on the real thing.
I've got the 6502 Krusader 1.3 version installed on my Replica1 to try to figure this out (this version can trace through code). I'll post my results when I've figured it out.
I'm wondering if anyone else out there has tried this, or has another way of seeing what's happening on real hardware in the meantime.
Here's my copy of hello.c and a build script. You'll have to fix the include line, put in the less than and greater than characters.
unsigned char hello = "Hello, World!";
unsigned char * p = hello;
export CC65_INC CC65_LIB
rm -f $1.lst $1.asm $1.o $1
## -v for verbose, -O for optimize
$CC65 -v -t replica1 -T -o $1.asm $1.c
## -l for output listing
$CA65 -v -t replica1 -o $1.o $1.asm
## For local config, use -C replica1.cfg with ld65 instead of -t replica1
$LD65 -v -t replica1 -o $1 replica1.o $1.o apple1.lib
./bintomon $1 > $1.hex
We have to determine where it fails. I assume you are sending the HEX file to the Replica 1 through the serial port. Make sure there is a long enough delay between characters and line breaks for the Replica 1 to process the input. If it looks like the data was sent without error, can you verify that the image in memory looks good? Any bad memory? I don't know of a good way to test this off the top of my head without writing a memory test program.
Try this. Instead of writing a C program which includes so much extra library stuff, try an assembly language program that is much smaller and easier to check for proper installation.
If your setup works on the emulators, I bet its a problem with the transfer over the serial port.
The original used a 6502, and most replicas appear to use a 65C02. This may be one cause of the challenge.
Here is a simpler HELLO WORLD program.
This is really about testing the CC65 tool chain, and identifying where the various emulators and the real thing differ. Most other programs (including a few hand assembled hello world programs) work fine on both real systems and emulators.
The only real Apple1 I have access to is VB's Replica1 with a Rockwell 65C02. If it is an 6502 opcode that is behaving different on a 65C02 enough to break this simple program, then I still would consider it a bug in CC65 that it's using it, and the various emulators that successfully run this for not emulating it properly. Identifying why it's crashing on the real thing should be the key here.
I've checked the transport (and memory) by having my Replica1 send the data back and comparing, no errors. Many other programs work fine using the same transport settings.
This is as simple a C program as you can write, but it's really about getting CC65 to build code that works on the real thing, and fixing all the emulators out there to be more accurate.
Or it could be just my system (I doubt this as it seems to run almost everything else), so someone please try this on other hardware and let me know. I can post the Hex if you don't want to mess with CC65.
Output from latest CC65 with all the patches, and the apple1 patch.
Source code and build script included in previous post.
0280: A2 FF 9A 20 8C 02 20 58
: 03 4C 00 FF 20 9E 02 A9
: 00 85 20 A9 F0 85 21 58
: 20 C1 02 4C 41 03 A9 EE
: 85 28 A9 03 85 29 A9 00
: A8 A2 00 F0 0A 91 28 C8
: D0 FB E6 29 CA D0 F6 C0
: 04 F0 05 91 28 C8 D0 F7
: 60 A0 00 F0 07 A9 CE A2
: 02 4C C9 03 60 00 A0 0E
: 20 AE 03 A0 0D B9 BB 03
: 91 20 88 10 F8 A5 20 A6
: 21 20 8D 03 A9 0D 20 2B
: 03 A0 01 20 76 03 A0 00
: 20 6B 03 D0 03 4C 18 03
: A0 01 20 76 03 85 24 86
: 25 20 64 03 A0 00 20 A5
: 03 A5 24 A6 25 A0 00 20
: 6B 03 20 2B 03 4C E9 02
: A9 0D 20 2B 03 A0 10 20
: 34 03 60 48 20 7D 03 20
: 2E 03 68 4C EF FF 18 20
: 7D 03 60 C8 48 18 98 65
: 20 85 20 90 02 E6 21 68
: 60 AD EE 03 AE EF 03 20
: 8D 03 AD F0 03 AE F1 03
: 20 8D 03 A0 04 4C CE 02
: A0 00 F0 07 A9 C9 A2 03
: 4C C9 03 60 18 69 01 90
: 01 E8 60 85 28 86 29 A2
: 00 B1 28 60 A0 01 B1 20
: AA 88 B1 20 60 A0 00 B1
: 20 E6 20 F0 01 60 E6 21
: 60 A9 00 A2 00 48 A5 20
: 38 E9 02 85 20 B0 02 C6
: 21 A0 01 8A 91 20 68 88
: 91 20 60 A0 00 91 20 C8
: 48 8A 91 20 68 60 98 49
: FF 38 65 20 85 20 B0 02
: C6 21 60 48 65 6C 6C 6F
: 2C 20 57 6F 72 6C 64 21
: 00 8D D7 03 8E D8 03 8D
: DE 03 8E DF 03 88 B9 FF
: FF 8D E8 03 88 B9 FF FF
: 8D E7 03 8C EA 03 20 FF
: FF A0 FF D0 E8 60
I appreciate you posting the output. The code seems to work, except that the string contains lower case letters. I don't know what the original Apple I display does with lower case letters. It may only display upper case and symbol characters:
I don't know what the original Apple I display does if the high bit of the character being displayed is zero. Most of the output from the Apple I monitor has the hi bit set, whereas the cc65 hello world program echoes characters with the hi bit clear. Possibly, the program runs but does not display anything on an original Apple I.
Perhaps, some C code before calling echo...
The Replica 1 is happy to echo characters with high bit 0, and I expect the original Apple 1 is the same. Does cc65 come with source for the Apple 1 version of it's standard libraries?
There was a patch for CC95 posted around here somewhere to target the replica1/apple1. It's not a very compete library, but it allows for the above program to compile (and at least run on Apple1 emulators).
I remember looking at the schematics for the Apple1, the spec sheet for the signetics 2513, as well as the video showing a real Apple1 running the following program:
0000: A9 0 AA 20 EF FF E8 8A 4C 2 0
The real Apple1 (and also my Replica1) outputs a bunch of characters and numbers, A-Z, a few more characters, then A-Z again, which taken all together means that if you try to print any character with the 7th bit set, it will print one of the 32 character set that includes the upper case letters. If the 7th isn't set and the 6th bit is set, then print the character set that includes the numbers. If nether the 7th and 6th are set, then it won't print anything (but it still waits for the vertical sync). The 8th bit is ignored (it's not connected).
You can see the video yourself at the bottom of this page... http://www.bytecollector.com/apple1/
Long story short, trying to output lower case should output upper case. It was a good observation though.
Thanks for reminding me about that video. It reassures me that the original Apple I echos upper case characters when lower case characters are output.
It seems that control characters do not do anything, except for carriage return. I don't think that the video shows what happens when characters with the 8th bit clear are output.
"If the first character of the operand is — sign the entire string will be in negative ASCII (128 .. 256), the way the Apple 1 likes to get its ASCII characters."
I wonder whether the 8th bit needs to be set to echo characters on the original Apple I?
No, the high (8th) bit is completely ignored.
If you want to test this, try this program...
300: A9 80 AA 20 EF FF E8 8A 9 80 4C 2 3
In the video, it's really showing two lines printed per loop through all possible X values, one for 0-7F, and again for 80-FF. The above program runs through just 80-FF.
Yes, control characters have both the 6th and 7th bits unset, so it will still wait for refresh, but won't print anything. That's why you see the pause after it prints each line.
You have to and the 8th bit for the apple 1. It really makes things interesting when doing programs but standard data needs the 8th bit set for the video.
I appreciate you commenting Vince.
Perhaps I am now even more confused
Did you mean to write:
You have to or the 8th bit, for the apple 1, because an AND instruction clears bits, and an OR instruction sets bits.
ORA #$80 ; set the 8th bit to one
JSR ECHO ; JSR $FFEF Apple 1 echo
For keyboard input, the high order bit is always 1. This bit is not cleared by the Woz monitor keyboard entry code or in Integer BASIC, hence the ASCII it codes are all non-standard by this bit.
For video out, the operation manual says:
Lower 7 bits are data output, high order bit is "display ready" input (1= ready, 0 = busy).
Now consider the monitor code:
From this it is apparent that the high order bit is relevant to checking the display output state, not to the data being submitted. On the Replica 1 hardware (and presumably the A-one since Krusader works on it and it never sets this bit) and all the Apple 1 emulators I've tried, video output does not require the high bit to be set.
Regarding the original problem, I'd recommend mapping the output code to the cc65 libraries used. In the quick look I had I could easily identify the standard initialisation sequence etc. You could then come up with a nice annotated source that would make it much easier to work out what is going wrong. I'd also try a version that just writes a single character with putc. If that also fails, it will be even easier to trace.
Yeah, sorry about that, have been away for too long on this stuff. On the Apple 1, replica 1 and I think the A-One, the keyboard input only inputs 7 bit ASCII and the 8th bit is pulled high to 5V. To work with data out it does ignore the 8th bit, sorry. The A-One would have to set the 8th bit high, check the schematics.
Now, if you were injecting data into the Woz monitor as if it were typed in but really came from an ACIA serial port, then ORA #$80 would be what you need to do to the incoming data. That's why Backspace "_" is #$DF and not $7F because the 8th bit is set on the keyboard port.
It has been some time since I submitted the Apple 1 patch. The CC65 guys didn't want it and told me not to use the conio library but the stdio library. Quite honestly, it hasn't had much QA. The latest patch I found on my drive was from Sep 12, 2006. Not sure if this matches what you downloaded. Here is a link:
You can use the standard hello world with this:
printf("Hello, Apple 1\n");
I just tried it and it works on my Replica 1. Not sure how much of the stdio library will work as I really hacked in the read/write routines.
If all you want is to send characters to the console and read in characters from the keyboard, I made very small, low level routines that avoid pulling in any other libraries. RAM is a rare commodity, even on a 32K Replica 1. Here is the world dumbest TV typewriter using these routines:
int main (void)
while (1) writevid(readkey());
Hope that helps you get going.
p.s. yeah, you have to replace the *** with brackets.
It looks like these patches are different than the ones I was using. I'm rebuilding my cc65 now. Thanks for posting this.
There still is the problem of why the emulators are running my "broken and backwards" code, but the real machines (at least my Replica1, others?) just spit out a string of 7's. I'm hoping to spend a few hours this weekend trying to find the answer.
Looks like at address $0376 it does a LDA ($20),Y, where $20,$21 is EC EF, and Y = 1.
This means it's reading a value (that it tried to modify earlier) at $EFED!!
On the Replica1, this is ROM, so it's bogus data. It spins printing 7's forever.
On my emulator, this is RAM (with BASIC loaded), so it works. BASIC is lobotomized.
In MESS and POM1, this also can be RAM.
On a real Apple 1 this should be RAM, so it might work.
Could someone with a real Apple 1 (or exact clone) with RAM at E000-EFFF please give this a spin and see what happens?
If it works, I'll call it a feature and start working on CFFA1 code.
... you are using to build with? When building for the replica 1 with 32K of RAM, I put the C stack at the top of the 32K. On an Apple 1, I put the C stack in the upper 4K, where BASIC would reside if it were loaded. That is why there are two build types - Replica1 and Apple1. That could be the part of your problem.