|
- ; ============================================================
- ; C64 HI-RES BITMAP DEMO
- ; Switches to 320x200 hi-res bitmap mode, draws a diagonal
- ; line, then waits for a key before restoring text mode.
- ;
- ; Assemble to $C000 and run with:
- ; LOAD"BITMAP",8,1 : SYS 49152
- ;
- ; Bitmap: $A000-$BFFF (8000 bytes, under BASIC ROM)
- ; Screen color RAM: $0400-$07E7 (1000 bytes)
- ; ============================================================
-
- * = $C000
-
- ; --- Zero-page pointers ---
- PTR = $FB ; 2-byte pointer
- BPTR = $FD ; 2-byte bitmap pointer
-
- ; --- Constants ---
- BITMAP = $A000 ; bitmap base
- SCREEN = $0400 ; color nybble RAM (foreground hi/background lo)
-
- START:
- JSR INIT_BITMAP
- JSR DRAW_DIAGONAL
- JSR WAIT_KEY
- JSR RESTORE_TEXT
- RTS
-
- ; ============================================================
- ; INIT_BITMAP
- ; Sets up VIC-II for hi-res bitmap mode
- ; ============================================================
- INIT_BITMAP:
- ; Turn off interrupts temporarily
- SEI
-
- ; Set VIC bank to 0 ($0000-$3FFF is default bank)
- ; Bitmap at $A000 requires bank 2 ($8000-$BFFF) — switch!
- LDA $DD00
- AND #$FC ; clear bits 0-1
- ORA #$01 ; bank 2: VIC sees $8000-$BFFF
- STA $DD00
-
- ; VIC memory setup: $D018
- ; Bitmap at $A000 = offset $2000 from bank base $8000
- ; $2000 >> 13 = bit 3 set → bitmap pointer bit = 1
- ; Screen RAM at $8400 (color nybbles) — offset $0400 >> 10 = $0 → bits 7-4 = 0001
- LDA #%00011000 ; screen at $8400 (bits 7-4 = 0001), bitmap at $A000 (bit 3)
- STA $D018
-
- ; Enable bitmap mode: $D011 bit 5 = 1
- LDA $D011
- ORA #%00100000
- STA $D011
-
- ; Multicolor off (hi-res): $D016 bit 4 = 0
- LDA $D016
- AND #%11101111
- STA $D016
-
- ; Set border color to black
- LDA #0
- STA $D020
-
- ; Set background color to black
- STA $D021
-
- ; Clear bitmap (8000 bytes of zeros = black pixels)
- LDA #<BITMAP
- STA PTR
- LDA #>BITMAP
- STA PTR+1
- LDA #0
- LDY #0
- LDX #$1F ; 32 pages = 8192 bytes (covers 8000)
- CLRLOOP:
- STA (PTR),Y
- INY
- BNE CLRLOOP
- INC PTR+1
- DEX
- BNE CLRLOOP
-
- ; Set all color RAM nybbles: foreground=white(1), background=black(0)
- ; Each byte = $10 = white fg, black bg
- LDA #<SCREEN
- STA PTR
- LDA #>SCREEN
- STA PTR+1
- LDA #$10
- LDY #0
- COLLOOP:
- STA (PTR),Y
- INY
- CPY #232 ; 1000 - 8 = 232? No: LDY loops 0-255 then second pass
- BNE COLLOOP
- ; Handle full 1000 bytes (4 pages)
- ; Simple approach: just fill $0400-$07E7
- LDX #3
- LDY #0
- COLLOOP2:
- STA (PTR),Y
- INY
- BNE COLLOOP2
- INC PTR+1
- DEX
- BNE COLLOOP2
-
- CLI
- RTS
-
- ; ============================================================
- ; DRAW_DIAGONAL
- ; Draws a white diagonal line from (0,0) to (199,199)
- ; In hi-res bitmap, pixel (x,y) is in:
- ; byte = bitmap + (y AND $F8)*40 + (x AND $F8) + (y AND 7)
- ; bit = 7 - (x AND 7)
- ; ============================================================
- DRAW_DIAGONAL:
- LDX #0 ; X pixel (0-199)
- DLOOP:
- TXA ; Y = X (diagonal)
- JSR SETPIXEL
- INX
- CPX #200
- BNE DLOOP
- RTS
-
- ; ============================================================
- ; SETPIXEL — set pixel (.X=x, .A=y)
- ; ============================================================
- SETPIXEL:
- ; Calculate byte address
- ; addr = $A000 + (Y>>3)*320 + (X>>3)*8 + (Y AND 7)
- ; Uses simple approach via table lookup or shift math
- STX XCOORD
- STA YCOORD
-
- ; Step 1: row base = (Y>>3) * 320
- ; Y>>3 * 320 = Y>>3 * 256 + Y>>3 * 64
- LSR ; Y>>1
- LSR ; Y>>2
- LSR ; Y>>3 (char row 0-24)
- TAX ; X = row number
- LDA ROWLO,X ; low byte of row base
- STA BPTR
- LDA ROWHI,X
- STA BPTR+1
-
- ; Step 2: add (X>>3)*8 = column offset
- LDA XCOORD
- LSR ; X>>1
- LSR ; X>>2
- LSR ; X>>3 (char col 0-39)
- ASL ; *2
- ASL ; *4
- ASL ; *8
- CLC
- ADC BPTR
- STA BPTR
- BCC NOINC1
- INC BPTR+1
- NOINC1:
- ; Step 3: add (Y AND 7) for sub-row
- LDA YCOORD
- AND #$07
- CLC
- ADC BPTR
- STA BPTR
- BCC NOINC2
- INC BPTR+1
- NOINC2:
- ; Step 4: add bitmap base $A000
- LDA BPTR+1
- CLC
- ADC #>BITMAP
- STA BPTR+1
- ; (low byte already correct)
-
- ; Step 5: set bit (7 - (X AND 7))
- LDA XCOORD
- AND #$07
- TAX
- LDA BITMASK,X
- LDY #0
- ORA (BPTR),Y
- STA (BPTR),Y
- RTS
-
- XCOORD: .BYTE 0
- YCOORD: .BYTE 0
-
- ; Bit masks for bit positions 7..0
- BITMASK:
- .BYTE %10000000 ; bit 7 (x mod 8 = 0)
- .BYTE %01000000
- .BYTE %00100000
- .BYTE %00010000
- .BYTE %00001000
- .BYTE %00000100
- .BYTE %00000010
- .BYTE %00000001 ; bit 0 (x mod 8 = 7)
-
- ; Row base address table (40*8 = 320 bytes per char row)
- ; Row N base = N * 320; precomputed for rows 0-24
- ROWLO:
- .BYTE <(0*320),<(1*320),<(2*320),<(3*320),<(4*320)
- .BYTE <(5*320),<(6*320),<(7*320),<(8*320),<(9*320)
- .BYTE <(10*320),<(11*320),<(12*320),<(13*320),<(14*320)
- .BYTE <(15*320),<(16*320),<(17*320),<(18*320),<(19*320)
- .BYTE <(20*320),<(21*320),<(22*320),<(23*320),<(24*320)
- ROWHI:
- .BYTE >(0*320),>(1*320),>(2*320),>(3*320),>(4*320)
- .BYTE >(5*320),>(6*320),>(7*320),>(8*320),>(9*320)
- .BYTE >(10*320),>(11*320),>(12*320),>(13*320),>(14*320)
- .BYTE >(15*320),>(16*320),>(17*320),>(18*320),>(19*320)
- .BYTE >(20*320),>(21*320),>(22*320),>(23*320),>(24*320)
-
- ; ============================================================
- ; WAIT_KEY — spin until any key pressed
- ; ============================================================
- WAIT_KEY:
- JSR $FFE4 ; GETIN
- BEQ WAIT_KEY
- RTS
-
- ; ============================================================
- ; RESTORE_TEXT — return to standard text mode
- ; ============================================================
- RESTORE_TEXT:
- ; Restore VIC bank 0
- LDA $DD00
- ORA #$03
- STA $DD00
-
- ; Restore VIC memory map ($D018)
- LDA #$15 ; screen at $0400, charset at $1000
- STA $D018
-
- ; Turn off bitmap mode
- LDA $D011
- AND #%11011111
- STA $D011
-
- ; Restore background/border
- LDA #14 ; light blue border (default)
- STA $D020
- LDA #6 ; blue background (default)
- STA $D021
-
- ; Clear screen
- LDA #147 ; PETSCII clear
- JSR $FFD2
-
- RTS
|