A C64 Game - Step 25

posted in New Old Things
Published October 01, 2011
Advertisement

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

step25.zip


Previous Step Next Step

Previous Entry A C64 game - Step 24
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement