Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; Flip Screen - v.2.0 (02/2025)
- ; Code by kimono (f. nardella)
- ; A program that flips both the character set and screen memory vertically and horizontally
- ; Compile with 64tass cross-assembler:
- ; 64tass -c -a --cbm-prg flip-screen.asm -o flipscreen.prg
- ; BASIC starter - creates a SYS command that jumps to our code
- * = $0801 ; Start of BASIC memory
- .word (+), 2025 ; Pointer to next BASIC line and line number
- .null $9e, format("%d", start) ; SYS token and start address
- + .word 0 ; End of BASIC program
- ; Memory location constants
- CHAR_MEM = $3000 ; New character set location (12288 decimal)
- INIT_SCREEN = $0400 ; Start of screen memory (1024 decimal)
- END_SCREEN = $07e7 ; End of screen memory (2023 decimal)
- BUFFER = $C800 ; Temporary buffer for screen data
- CHARSET_ROM = $D000 ; Location of character ROM (53248 decimal)
- VIC_CR = $D018 ; VIC-II control register for character set location
- MEM_CONFIG = $01 ; CPU memory configuration register
- * = $1000 ; Program code starts at $1000
- start:
- ; Initialize by disabling interrupts and switching character ROM to RAM
- sei ; Disable interrupts to prevent timing issues
- lda MEM_CONFIG ; Load current memory configuration
- and #$FB ; Clear bit 2 to enable RAM under ROM
- sta MEM_CONFIG ; Store new configuration
- ; Copy character ROM to RAM in 6 blocks of 256 bytes each
- ; Each block is copied and each character is flipped horizontally using the lookup table
- copy_loop: ; First 256 bytes
- lda CHARSET_ROM, x
- jsr flip_bits ; Flip each byte horizontally
- sta CHAR_MEM, x
- inx
- bne copy_loop ; Continue until X wraps around (256 times)
- copy_loop2: ; Second 256 bytes
- lda CHARSET_ROM + $FF, x
- jsr flip_bits
- sta CHAR_MEM + $FF, x
- inx
- bne copy_loop2
- copy_loop3: ; Third 256 bytes
- lda CHARSET_ROM + 2 * $FF, x
- jsr flip_bits
- sta CHAR_MEM + 2 * $FF, x
- inx
- bne copy_loop3
- copy_loop4: ; Fourth 256 bytes
- lda CHARSET_ROM + 3 * $FF, x
- jsr flip_bits
- sta CHAR_MEM + 3 * $FF, x
- inx
- bne copy_loop4
- copy_loop5: ; Fifth 256 bytes
- lda CHARSET_ROM + 4 * $FF, x
- jsr flip_bits
- sta CHAR_MEM + 4 * $FF, x
- inx
- bne copy_loop5
- copy_loop6: ; Sixth 256 bytes
- lda CHARSET_ROM + 5 * $FF, x
- jsr flip_bits
- sta CHAR_MEM + 5 * $FF, x
- inx
- bne copy_loop6
- ; Copy flipped character set to buffer for vertical flipping
- ldx #<CHAR_MEM ; Set up source pointer low byte
- stx $FA
- ldx #>CHAR_MEM ; Set up source pointer high byte
- stx $FB
- ldx #<BUFFER ; Set up destination pointer low byte
- stx $FC
- ldx #>BUFFER ; Set up destination pointer high byte
- stx $FD
- ldy #0
- ciclo: ; Copy loop for character set
- lda ($FA), y ; Load byte from source
- sta ($FC), y ; Store byte in buffer
- iny
- bne ciclo ; Continue for 256 bytes
- inc $FB ; Increment high bytes of pointers
- inc $FD
- ldx $FB
- cpx #$35 ; Check if we've copied all characters
- bne ciclo
- ; Prepare to flip characters vertically
- ldx #<CHAR_MEM ; Reset pointers for vertical flip
- stx $FA
- ldx #>CHAR_MEM
- stx $FB
- ldx #<BUFFER
- stx $FC
- ldx #>BUFFER
- stx $FD
- ; Flip each character vertically (7 bytes per character)
- flip_all_chars_loop:
- ldx #6 ; Start from bottom row (6)
- ldy #0 ; Start reading from top row (0)
- C1:
- lda ($FC), y ; Read byte from buffer
- sta $02 ; Store temporarily
- tya ; Save Y
- pha
- txa ; Use X as new Y for inverted write
- tay
- lda $02 ; Get stored byte
- sta ($FA), y ; Write to new position
- pla ; Restore Y
- tay
- iny ; Next source byte
- dex ; Previous destination position
- cpy #7 ; Check if we've done all 7 rows
- bne C1
- ; Move to next character in buffer
- clc
- lda $FC
- adc #8 ; Each character is 8 bytes
- sta $FC
- bcc skip1
- inc $FD
- skip1:
- ; Move to next character in destination
- clc
- lda $FA
- adc #8
- sta $FA
- bcc skip2
- inc $FB
- skip2:
- ; Check if we've processed all characters
- lda $FB
- cmp #$35 ; End of character set
- bne flip_all_chars_loop
- ; Copy screen memory to buffer for flipping
- ldx #<INIT_SCREEN
- stx $FA
- ldx #>INIT_SCREEN
- stx $FB
- ldx #<BUFFER
- stx $FC
- ldx #>BUFFER
- stx $FD
- ldy #0
- ciclo1: ; Copy screen memory to buffer
- lda ($FA), y
- sta ($FC), y
- iny
- bne ciclo1
- inc $FB
- inc $FD
- ldx $FB
- cpx #8 ; Check if we've copied all screen memory
- bne ciclo1
- ; Flip screen memory vertically in four 256-byte blocks
- flip_screen_loop: ; First block
- lda BUFFER, x ; Read from start of buffer
- sta END_SCREEN - $FF, y ; Write to end of screen
- inx
- dey
- bne flip_screen_loop
- flip_screen_loop2: ; Second block
- lda BUFFER + $FF, x
- sta END_SCREEN - 2 * $FF, y
- inx
- dey
- bne flip_screen_loop2
- flip_screen_loop3: ; Third block
- lda BUFFER + 2 * $FF, x
- sta END_SCREEN - 3 * $FF, y
- inx
- dey
- bne flip_screen_loop3
- flip_screen_loop4: ; Fourth block
- lda BUFFER + 3 * $FF, x
- sta END_SCREEN - 4 * $FF, y
- inx
- dey
- bne flip_screen_loop4
- ; Cleanup and finish
- lda MEM_CONFIG ; Restore ROM configuration
- ora #$04 ; Set bit 2 to enable ROM
- sta MEM_CONFIG
- cli ; Re-enable interrupts
- ; Point VIC-II to new character set
- lda VIC_CR
- and #$F0 ; Clear lower nibble
- ora #$0C ; Set to point to $3000
- sta VIC_CR
- rts ; Return from subroutine
- ; Subroutine to flip bits in a byte horizontally
- flip_bits:
- tay ; Use byte as index into lookup table
- lda bit_flip_table, y ; Get flipped byte from table
- rts
- ; Lookup table for bit flipping
- ; Each byte in the table contains the bit-reversed pattern of its index
- ; For example: Input 0000 0001 ($01) returns 1000 0000 ($80)
- bit_flip_table:
- .byte $00, $80, $40, $C0, $20, $A0, $60, $E0
- .byte $10, $90, $50, $D0, $30, $B0, $70, $F0
- .byte $08, $88, $48, $C8, $28, $A8, $68, $E8
- .byte $18, $98, $58, $D8, $38, $B8, $78, $F8
- .byte $04, $84, $44, $C4, $24, $A4, $64, $E4
- .byte $14, $94, $54, $D4, $34, $B4, $74, $F4
- .byte $0C, $8C, $4C, $CC, $2C, $AC, $6C, $EC
- .byte $1C, $9C, $5C, $DC, $3C, $BC, $7C, $FC
- .byte $02, $82, $42, $C2, $22, $A2, $62, $E2
- .byte $12, $92, $52, $D2, $32, $B2, $72, $F2
- .byte $0A, $8A, $4A, $CA, $2A, $AA, $6A, $EA
- .byte $1A, $9A, $5A, $DA, $3A, $BA, $7A, $FA
- .byte $06, $86, $46, $C6, $26, $A6, $66, $E6
- .byte $16, $96, $56, $D6, $36, $B6, $76, $F6
- .byte $0E, $8E, $4E, $CE, $2E, $AE, $6E, $EE
- .byte $1E, $9E, $5E, $DE, $3E, $BE, $7E, $FE
- .byte $01, $81, $41, $C1, $21, $A1, $61, $E1
- .byte $11, $91, $51, $D1, $31, $B1, $71, $F1
- .byte $09, $89, $49, $C9, $29, $A9, $69, $E9
- .byte $19, $99, $59, $D9, $39, $B9, $79, $F9
- .byte $05, $85, $45, $C5, $25, $A5, $65, $E5
- .byte $15, $95, $55, $D5, $35, $B5, $75, $F5
- .byte $0D, $8D, $4D, $CD, $2D, $AD, $6D, $ED
- .byte $1D, $9D, $5D, $DD, $3D, $BD, $7D, $FD
- .byte $03, $83, $43, $C3, $23, $A3, $63, $E3
- .byte $13, $93, $53, $D3, $33, $B3, $73, $F3
- .byte $0B, $8B, $4B, $CB, $2B, $AB, $6B, $EB
- .byte $1B, $9B, $5B, $DB, $3B, $BB, $7B, $FB
- .byte $07, $87, $47, $C7, $27, $A7, $67, $E7
- .byte $17, $97, $57, $D7, $37, $B7, $77, $F7
- .byte $0F, $8F, $4F, $CF, $2F, $AF, $6F, $EF
- .byte $1F, $9F, $5F, $DF, $3F, $BF, $7F, $FF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement