4

I have some 6502 code to print a string to the screen memory after clearing the screen. Unfortunately if I print a string, for example "HELLO WORLD", it will come out in garbled characters. I've found that this is because the upper case characters start at 0x01, not 0x41 as I thought from the PETSCII codes here.

I can fix this by subtracting 0x40 from my string, but then everything other than letters are incorrect, for example, spaces. I'm just not sure why the character generator is turning 0x01 into the character 'A' and not 0x41. It turns 0x41 into an inverted spade sign (like on a deck of cards) and everything above it seems to be border characters and weird symbols.

After looking around for a while I found this quote on the wikipedia page for PETSCII which seemed to state the problem I'm trying to solve, but I'm not sure how to fix it and can't find any information anywhere...

The actual character generator ROM used a different set of assignments. For example, to display the characters "@ABC" on screen by directly POKEing the screen memory, one would POKE the decimal values 0, 1, 2, and 3 rather than 64, 65, 66, and 67.

I am running on the VICE x64 emulator on Mac OS X, and I'm assembling with an OS X port of 64tass.

This is the assembly code without subtracting 0x40:

*=$c000

BORDER = $d020
INNER = $d021

start   lda #0
        sta BORDER
        lda #0
        sta INNER

        jsr clear
        jsr string

loop    
        jmp loop


clear   ; clear screen
        lda #$00
        tax
        lda #$20
clrloop 
        sta $0400, x ; clear each memory "row"
        sta $0500, x
        sta $0600, x
        sta $0700, x
        dex
        bne clrloop  ; clear if x != 0
        rts

string  ; load string
        ldx #$0
strloop lda hello, x ; load each byte in turn
        cmp #0       ; if we reached a null byte, break
        beq strexit
        sta $0400, x
        inx
        jmp strloop
strexit rts


hello   .text "HELLO WORLD"
        .byte 0

Here is a screenshot of the output

Here is a screenshot of the output

Thanks to everyone in the comments!

Side note to help others

You can set which row and column CHROUT will output to by setting the cursor position with PLOT

http://sta.c64.org/cbm64krnfunc.html

Joe Bentley
  • 296
  • 2
  • 13
  • Have you read this: http://wpguru.co.uk/2014/06/how-to-switch-between-upperlower-case-and-petscii-fonts-on-a-c64/ ? – Michael Sep 10 '14 at 17:35
  • @Michael I will try this, but even in unshifted mode it should show upper case letters at 0x40 according to the PETSCII chart http://upload.wikimedia.org/wikipedia/commons/c/c4/C64_Petscii_Charts.png – Joe Bentley Sep 10 '14 at 17:43
  • 4
    Any C=64 programming manual should have 2 character tables for you to refer to: screen codes and PETSCII. When you're storing characters to the screen at $400, you use screen codes. [Google c64 screen codes](http://www.google.com/search?q=c64+screen+codes) -> http://sta.c64.org/cbm64scr.html –  Sep 10 '14 at 17:44
  • Thank you, I was not aware of that! I found a conversion tool here http://sta.c64.org/cbm64pettoscr.html – Joe Bentley Sep 10 '14 at 17:47
  • Okay, @Michael's suggestion seems to work, that is, changing to the upper/lower case character set seems to fix this and let me use 0x40 as the expected characters. Okay this makes sense as it pushes the letters into the higher end in the screen code chart. Unfortunately this doesn't work for lower case letters, so different conversion is needed in that case. – Joe Bentley Sep 10 '14 at 17:50
  • By the way, the usual technique for printing characters to the string from a PETSCII source is to call CHROUT –  Sep 10 '14 at 17:59

1 Answers1

8

You're possibly writing ASCII codes into the screen memory directly, that's why it's offset by $40.

To have them in PETSCII, you need to add the "-a" option to 64tass. But that alone is not enough. Your example will be offset by $c0 (uppercase PETSCII letters) now. Changing the text to lowercase still gives $40 offset (lowercase PETSCII).

You need to write "screen" codes to the screen. Fortunately there's a built in conversion in 64tass if you do it like this:

        .enc screen            ; switch to screen code encoding
hello   .text "hello world"
        .byte 0
        .enc none

But remember that "@" is 0 in screen code, so it'll termitate your loop. The text is in lower case, but as the default font is uppercase it'll end up uppercase. Set $d018 to $16 to switch to a lower case font, then it'll match what you write.

A proper PETSCII example would be:

    *=$c000

    lda #0
    sta $d020 ; border
    sta $d021 ; background

    ldx #0
lp  lda hello,x
    beq end
    jsr $ffd2 ;print character
    inx
    bne lp
end rts

hello .null "{clr}{swlc}HELLO WORLD"

Compile it with a not too old 64tass which translates "{clr}" and "{swlc}" to control codes 147 and 14. And don't forget the "-a" switch to enable Unicode support, otherwise the assembler won't do any translation of the string and will copy it verbatim (as raw bytes).

guest01
  • 96
  • 1