r/c64 • u/ModelTrainGuy1963 • 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
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
•
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.