6809 request: smallest 64K test?

Okay, 6809 folks… In my 64K TRS-80 CoCo memory test article, I used an assembly language program of unknown origin to copy the CoCo’s ROM in to RAM. The “test” part is POKEing a byte in to ROM space and seeing if it now changes (since, on a 64K system, it would be running out of RAM).

The BASIC “OK” prompt is changed to read “OY” (after placing the 64K CoCo in to all-RAM mode).

That code looks like it was built for speed, moving 6 bytes at a time by using three 16-bit registers (X, Y and U). As a refresher, here is that code:

start:
    PSHS CC
    ORCC #$50
    LDY #$8000
loop1:    
    STA $FFDE
    LDD ,Y
    LDX $02,Y
    LDU $04,Y
    STA $FFDF
    STD ,Y++
    STX ,Y++
    STU ,Y++
loop2:    
    CMPY #$FEFC
    BCS loop1
    CMPY #$FF00
    BCC done
    STA $FFDE
    LDD ,Y
    STA $FFDF
    STD ,Y++
    BRA loop2
done:    
    PULS CC
    RTS

I presented this routine as a BASIC loader program so one could easily type it in rather than needing an assembler and typing in assembly source code to compile.

For folks patient enough to type in a whole CoCo screen full of hexadecimal DATA statements, it works fine. But I thought it might be finer to present an even smaller program with less DATA statements.

The program size can almost be cut in half by eliminating the first loop that copies the 6 bytes at a time. Instead, I came up with something like this:

start:
    PSHS CC     Save CC
    ORCC #$50   Mask interrupts
    
    LDX #$8000  Start of ROM
loop:    
    STA $FFDE   Enable ROM
    LDD ,X      Load D with whatever is at X
    STA $FFDF   Disable ROM
    STD ,X++    Store D at X and increment X
    CMPX #$FF00 Is X past end of ROM?
    BNE loop    If not, repeat

    PULS CC     Restore CC
    RTS         Return

The original “need for speed” version compiled to 53 bytes. This new version compiles to 25 bytes. That would make it much easier to type in, like this:

0 REM 64K ROM TO RAM (25)
10 FOR L=16128 TO 16152
20 READ V:POKE L,V
30 NEXT
40 EXEC 16128:POKE 44015,89
80 DATA 52,1,26,80,142,128,0
90 DATA 183,255,222,236,132
100 DATA 183,255,223,237,129
110 DATA 140,255,0,38,241,53
120 DATA 1,57

Is there anything I can do to save a few bytes in that ROM to RAM routine? Please share comments and suggestions.

Is there an easier way to detect 64K? (Hey, that rhymes!)

If the goal is to just test for the existence of 64K, all we really need to do is put the machine in RAM mode and try to modify a byte in the upper 32K. If it can be modified, 64K is there. Maybe there is an even smaller way just to do that?

In 64K, you have memory locations 0-65535 available ($0000-$FFFF). But, the last 255 bytes ($FF00-$FFFF) are used for I/O, and as far as I know, the RAM there cannot be accessed. (Is this correct?) That would mean the last byte of usable RAM on a 64K CoCo would be at $FF00-1 ($FEFF). If that is correct, all we need to do is switch to RAM mode, store a byte at $FEFF and then read it back and see if it is what we put there. If it is, 64K exists.

There is a ROM routine that will output whatever character is loaded in the A register. We could use that to print out a message if 64K exists. Since the goal is to make this as small as possible, the message could simply be ‘Y’. My first attempt was something like this:

start:
    PSHS CC     Save CC
    ORCC #$50   Mask interrupts.
    
    STA $FFDF   Disable ROM
    LDA #'Y     Load A with 'Y'
    STA $FEFF   Store A in last RAM byte
    CLRA        Clear A
    LDA $FEFF   Load A with last RAM byte
    CMPA #'Y    Compare to 'Y'
    BEQ done    If Y, done.
    LDA #'N     Else, load A with 'N'
done:
    STA $FFDE   Enable ROM
    PULS CC     Restore CC
    JSR [$A002] Output byte in A to console.

    RTS         Return

I disable the ROM (going in to “all RAM mode”), load A with a ‘Y’ character, then store it at $FEFF. I then clear A, then load A with whatever is at $FEFF. I compare A with ‘Y’ and if it is, I branch to the end where it will re-enable ROM, restore the CC register, then jump to the ROM routine that outputs whatever is in A. If it had no equaled ‘Y’, it would have not branched to ‘done’ and would instead load A with ‘N’, then complete, outputting ‘N’.

Running that should print out Y or N, depending on if 64K is detected.

And it works! But it is larger than the 64K ROM TO RAM code, taking up 32 bytes. I suppose there could be less typing since now the “ROM to RAM” program wouldn’t need to POKE the ‘OK’ prompt to show the user if it can be changed, so this probably is better.

0 REM 64KTEST1.BAS (32)
10 FOR L=16128 TO 16159
20 READ V:POKE L,V
30 NEXT
40 EXEC 16128
50 DATA 52,1,26,80,183,255,223
60 DATA 134,89,183,254,255,79
70 DATA 182,254,255,129,89,39
80 DATA 2,134,78,183,255,222
90 DATA 53,1,173,159,160,2,57

However … If we don’t want to be as user-friendly (printing a ‘Y’ or ‘N’), maybe some bytes could be saved by just setting a byte on the 32-column screen to indicate the result. I tried this:

start:
    PSHS CC     Save CC
    ORCC #$50   Mask interrupts.
    
    STA $FFDF   Disable ROM
    CLR $FEFF
    DEC $FEFF
    LDA $FEFF
done:
    STA $FFDE   Enable ROM
    PULS CC     Restore CC
    STA $0400

    RTS         Return

For this routine, I save CC and disable interrupts, then disable ROM. I then clear memory location $FEFF, and then try to Decrement whatever is there. If the CLR worked, it should be 0, and a DEC would turn it in to 255. To see what happened, I load A with whatever is at $FEFF, re-enable ROM, restore CC and then store whatever I loaded in to A to the top left of the 32 column screen. If 64K is present, an orange graphics block (255) should appear in the top left of the screen. If not, whatever value in ROM at $FEFF will be stored that. On my CoCo, that is a 0, so I should see an inverted ‘@’ sign appear on a non-64K system. This isn’t perfect, since if ROM just happened to contain 255 at that location, this test would not work.

This is 25 bytes of code. Still no savings, but the BASIC program could be smaller, which is the end goal:

0 REM 64KTEST2.BAS (25)
10 FOR L=16128 TO 16152
20 READ V:POKE L,V
30 NEXT
40 EXEC 16128
50 DATA 52,1,26,80,183,255,223
60 DATA 127,254,255,122,254
70 DATA 255,182,254,255,183
80 DATA 255,222,53,1,183,4,0,57

Line 40 should really be “CLS:PRINT:EXEC 16128”, otherwise the user would have to make sure they weren’t at the end of the screen when they ran it, since the next output would scroll and overwrite whatever the program POKEd to the top left of the screen.

Is this good enough?

Do you have better ideas?

Please share your thoughts in the comments.

Until next time…

7 thoughts on “6809 request: smallest 64K test?

  1. Dave Philipsen

    A small thing. If you’re going to push and pull CC you might as well combine the pull of cc and the rts at the end as PULS CC,PC. That saves you a byte.

    Reply
  2. Dave Philipsen

    Yes, PULS PC is the same as RTS. Saving CC is necessary if you want to unmask the interrupts when you return to BASIC.

    Reply
  3. Darren A

    “In 64K, you have memory locations 0-65535 available ($0000-$FFFF). But, the last 255 bytes ($FF00-$FFFF) are used for I/O, and as far as I know, the RAM there cannot be accessed. (Is this correct?)”

    You can access the last 256 bytes of a 64K RAM machine, but not at those addresses. You have to be in RAM/ROM mode and set the SAM’s Page Switch to ‘1’. This switches the Ram address “page” at 0000-7FFF to the use the upper half of the RAM rather then the lower half, putting those usually inaccessible bytes at 7F00-7FFF. A bit tricky to accomplish since switching the page means you lose access to the “normal” 32K of RAM.

    Reply

Leave a Reply to Dave PhilipsenCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.