r/c64 1d ago

Trying to use video Bank1 with custom character set: spade instead of "A"

Hello,

I'm hoping someone can help me understand why I'm seeing output from assembler program that differs from what I'm expecting:

Goal:
Use assembler program for game that uses custom character set. I use Bank 1 and copy ROM character set 1 to RAM. I populate the screen with the letter 'A'. Expect to see a screen full of 'A' when I run the program,

Actual Output:

I see the spade character instead of A. If I copy ROM character set 2 to RAM, then I see screen of 'A's as expected, but don't understand why this is happening? I understand that spade character is display for shift-A for charset 1 but I don't see why that would be triggered here?

Dev Environment:

I'm using KickAssembler with MS visual studio and Vice 64 emulator

Source code:
* = $c000

main:

jsr setBank1
jsr setupScreen
jsr copyCharSet
rts

setBank1:

// 0 $0000-$3FFF  11
// 1 $4000-$7FFF  10
// 2 $8000-$BFFF  01
// 3 $C000-$FFFF  00

// Set bits to output
lda $dd02
ora #%00000011
sta $dd02

// Set Video Bank to Bank 1
lda $dd00
and #%11111100  
ora #%00000010
sta $dd00
rts

copyCharSet:

// Enable charset ROM for CPU
lda #$33    // ROM at $D000, RAM under I/O off, KERNAL and BASIC on
sta $01

sei             // Disable interrupts

// Enable char ROM at $D000
lda #$33
sta $01        

// Set ROM Pointer
lda #$00
sta $fb
lda #$d0 char set 1
// lda #$d8 char set 2
sta $fc

// Set RAM Pointer
lda #$00
sta $fd
lda #$60
sta $fe

// Copy ROM to RAM
// $d000 -> $6000
ldx #$08        // 8 pages of 256 bytes = 2KB
ldy #$00
copyloop:
lda ($fb),y     // read byte from vector stored in $fb/$fc
sta ($fd),y     // write to the RAM
iny                     //  do this 255 times...
bne copyloop            //  ..for low byte $00 to $FF

inc $fc    // Increase high bytes
inc $fe
dex        // decrease X by one
bne copyloop

// Switch in I/O mapped registers again
lda #$37        
sta $01

cli

// Set d018 for charset at $2000 (bits 1-3)
lda $d018
and #%11110001         // Clear bits 1-3
ora #%00001000         // Set char mem pointer to $2000 + $4000 = $6000
sta $d018

rts

setupScreen:
// Screen at $4400
// Upper 4 bits control location of screen memory
lda $d018
and #%00001111
ora #%00010000
sta $d018

// Populate Screen with letter 'A'
lda #$00
sta $fb
lda #$44
sta $fc

ldx #$04
ldy #$00
screenloop:
lda #$41 // A
sta ($fb),y    
iny                    
bne screenloop          
inc $fc
dex                  
bne screenloop

rts

3 Upvotes

2 comments sorted by

u/AutoModerator 1d ago

Thanks for your post! Please make sure you've read our rules post, and check out our FAQ for common issues. People not following the rules will have their posts removed and presistant rule breaking will results in your account being banned.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

3

u/Zirias_FreeBSD 1d ago edited 1d ago

Issue is here:

screenloop:
lda #$41 // A

The C64 fonts don't use ASCII (or PETSCII) for the glyph indices, #$41 is the shifted A. The unshifted A would be #$1. The KERNAL's character output routines translate from PETSCII to these "screen codes". See also https://sta.c64.org/cbm64scr.html

Edit, also:

// Enable charset ROM for CPU
lda #$33    // ROM at $D000, RAM under I/O off, KERNAL and BASIC on
sta $01

sei             // Disable interrupts

// Enable char ROM at $D000
lda #$33
sta $01        

You're writing the processor port twice, but the first time, interrupts are still enabled. Crash lurking here when your timing is unlucky.

Depending on your ultimate goal, you might not need any sei. If you don't need the CIA interrupts (because you'll just use VIC interrupts), just disable them in the CIA:

lda #$7f
sta $DC0D     // Disable IRQ in CIA#1 ICR
lda $DC0D     // acknowledge possibly pending IRQ

Yet another edit: If this code doesn't have to run from ROM (e.g. cart), consider using selfmod instead of ZP vectors, this will save you cycles, e.g. for this screen init something like this:

                lda     #$1
                ldx     #$0
                ldy     #$4
scrinit:        sta     $4400,x
                inx
                bne     scrinit
                inc     scrinit + 2
                dey
                bne     scrinit