Time to spruce up the title screen again.
This time we split the title screen display, upper part will be a bitmap logo, lower path text mode.
Some clarification: The graphic chip of the C64, the VIC II, has some neat features. It displays line per line whatever mode currently is set. This means, with skilled modification you can change the mode while a screen is being displayed.
The VIC II aids the programmer with a raster interrupt. You can provide a line number where a interrupt should occur. This avoids having to actively wait. Since we need to show two modes we need to toggle modes two times.
Once the raster is above the inner visible area we activate the bitmap mode. Once the raster hits the end of the bitmap we want to display switch to text mode again. There's a bit more to it if you want exact splits, but the way the image is set up allows us to approach that rather naively.
The bitmap data itself was created by a Lua script from an actual image. Note that a bitmap is compiled of several parts: The actual image data, the color ram part (for 1 of the three possible colors per cell) and the screen data (for the other two possible colors per cell).
Bitmap data cannot be put in memory randomly, there are only a handful of aligned locations where they need to reside. Nice trick: Since the layout of the code is completely fixed you can actually force the compiler to put data at a specific location. This way you avoid to having to copy the bitmap data somewhere else.
Here we store the bitmap data at $2000:
;place the data at a valid bitmap position, this avoids copying the data
* = $2000
TITLE_LOGO_BMP_DATA
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
...
One of the color parts can also be fixed in memory:
* = $2c00
TITLE_LOGO_SCREEN_CHAR
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
!byte 0,0,0,0,0,0,0,0,0,0,32,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
...
The final part is copied to its required target location on demand:
TITLE_LOGO_COLORRAM
!byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
...
During settup up the title screen state we need to copy the color information to the color RAM. Since we only need 64 pixel height for the logo we only copy 320 bytes:
ldx #0
.FillColor
lda TITLE_LOGO_COLORRAM,x
sta SCREEN_COLOR,x
inx
bne .FillColor
.FillColor2
lda TITLE_LOGO_COLORRAM + 256,x
sta SCREEN_COLOR + 256,x
inx
cpx #( 320 - 256 )
bne .FillColor2
Now to set up the initial raster interrupt. Note that before doing that we call jsr WaitFrame once so the raster line is at a specific location. You don't want to hit the interrupt on the wrong side.
;-----------------------------------
;init IRQ
;-----------------------------------
!zone InitTitleIRQ
InitTitleIRQ
sei
lda #$37 ; make sure that IO regs at $dxxx
sta $1 ;are visible
lda #$7f ;disable cia #1 generating timer irqs
sta $dc0d ;which are used by the system to flash cursor, etc
lda #$1 ;tell VIC we want him generate raster irqs
sta $d01a
lda #$10 ;nr of rasterline we want our irq occur at
sta $d012
lda #$1b ;MSB of d011 is the MSB of the requested rasterline
sta $d011 ;as rastercounter goes from 0-312
;set irq vector to point to our routine
lda #<IrqSetBitmapMode
sta $314
lda #>IrqSetBitmapMode
sta $315
;acknowledge any pending cia timer interrupts
;this is just so we are 100% safe
lda $dc0d
lda $dd0d
cli
rts
Note the routine IrqSetBitmapMode (and IrqSetTextMode). These routines set their respective mode and setup the raster interrupt for the other part.
;-----------------------------------
;IRQ Title - set bitmap mode
;-----------------------------------
!zone IrqSetBitmapMode
IrqSetBitmapMode
;acknowledge VIC irq
lda $d019
sta $d019
;install top part
lda #<IrqSetTextMode
sta $314
lda #>IrqSetTextMode
sta $315
;nr of rasterline we want our irq occur at
lda #$71
sta $d012
;bitmap modus an
lda #$3b
sta $D011
;set VIC to bank 0
lda $DD00
and #$fc
ora #$3
sta $dd00
;bitmap to lower half, screen char pos at 3 * 1024 ( + 16384)
lda #%10111000
sta $D018
JMP $ea31
;-----------------------------------
;IRQ Title - set text mode
;-----------------------------------
!zone IrqSetTextMode
IrqSetTextMode
;acknowledge VIC irq
lda $d019
sta $d019
;install scroller irq
lda #<IrqSetBitmapMode
sta $314
lda #>IrqSetBitmapMode
sta $315
;nr of rasterline we want our irq occur at
lda #$10
sta $d012
;disable bitmap mode
lda #$1b
sta $D011
;set VIC to bank 3
lda $DD00
and #$fc
sta $dd00
;bitmap to lower half, screen char pos at 3 * 1024 ( + 16384)
lda #%00111100
sta $D018
jmp $ea31
Once the title screen state is left the interrupt needs to be disabled:
;-----------------------------------
;release IRQ
;-----------------------------------
!zone ReleaseTitleIRQ
ReleaseTitleIRQ
sei
lda #$37 ; make sure that IO regs at $dxxx
sta $1 ;are visible
lda #$ff ;enable cia #1 generating timer irqs
sta $dc0d ;which are used by the system to flash cursor, etc
;no more raster irqs
lda #$00
sta $d01a
lda #$31
sta $314
lda #$EA
sta $315
;acknowledge any pending cia timer interrupts
;this is just so we are 100% safe
lda $dc0d
lda $dd0d
cli
rts