Advertisement
felixnardella

Flip Screen

Feb 12th, 2025 (edited)
657
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
6502 TASM/64TASS 9.73 KB | Source Code | 0 0
  1. ; Flip Screen - v.2.0 (02/2025)
  2. ; Code by kimono (f. nardella)
  3. ; A program that flips both the character set and screen memory vertically and horizontally
  4. ; Compile with 64tass cross-assembler:
  5. ; 64tass -c -a --cbm-prg flip-screen.asm -o flipscreen.prg
  6.  
  7.  
  8. ; BASIC starter - creates a SYS command that jumps to our code
  9.  *   = $0801                          ; Start of BASIC memory
  10.      .word (+), 2025                  ; Pointer to next BASIC line and line number
  11.      .null $9e, format("%d", start)   ; SYS token and start address
  12.  + .word 0                            ; End of BASIC program
  13.  
  14. ; Constants
  15. CHAR_MEM = $3000       ; New character set starting at 12288 ($3000 in hex)
  16. INIT_SCREEN = $0400    ; Screen memory starting at 1024 ($0400 in hex)
  17. END_SCREEN = $07e7     ; Screen memory ending at 2023 ($07e7 in hex)
  18. BUFFER = $C800         ; Temporary buffer for screen flipping
  19. CHARSET_ROM = $D000    ; Original character set ROM starting at 53248 ($D000 in hex)
  20. VIC_CR = $D018         ; VIC-II control register for character set address (53272)
  21. MEM_CONFIG = $01       ; Memory configuration register
  22.  
  23.     * = $1000          ; Start of program at $1000
  24.  
  25. start:
  26. ; write the message
  27.     ldx #0                   ; Initialize index to zero
  28. loop:
  29.     lda message,x    ; Load character from message
  30.     jsr $FFD2        ; Call CHROUT to print character
  31.     inx              ; Increment index
  32.     cpx #$14          ; Check if end of string
  33.     bne loop         ; Continue until end of string
  34.  
  35. ; Initialize by disabling interrupts and switching character ROM to RAM
  36.     sei                ; Disable interrupts
  37.     lda MEM_CONFIG
  38.     and #$FB           ; Clear bit 2 to enable RAM under ROM
  39.     sta MEM_CONFIG
  40.  
  41. ; Copy character ROM to RAM in 6 blocks of 256 bytes each
  42. ; Each block is copied and each character is flipped horizontally using the lookup table
  43. ; First 256 bytes
  44.     ldx #$00   ; Azzeriamo X per il loop esterno
  45. copy_loop:
  46.     lda CHARSET_ROM, x
  47.     jsr flip_bits       ; Flip bits horizontally
  48.     sta CHAR_MEM, x
  49.     inx
  50.     bne copy_loop  ; Continue until X wraps around (256 times)
  51.  
  52. ; Second 256 bytes
  53.     ldx #$00   ; Reset X for the outer loop
  54. copy_loop2:
  55.     lda CHARSET_ROM + $FF, x
  56.     jsr flip_bits       ; Flip bits horizontally
  57.     sta CHAR_MEM + $FF, x
  58.     inx
  59.     bne copy_loop2  ; Continue until X wraps around (256 times)
  60.  
  61. ; Third 256 bytes
  62.     ldx #$00   ; Reset X for the outer loop
  63. copy_loop3:
  64.     lda CHARSET_ROM + 2 * $FF, x
  65.     jsr flip_bits       ; Flip bits horizontally
  66.     sta CHAR_MEM + 2 * $FF, x
  67.     inx
  68.     bne copy_loop3  ; Continue until X wraps around (256 times)
  69.  
  70. ; Fourth 256 bytes
  71.     ldx #$00   ; Reset X for the outer loop
  72. copy_loop4:
  73.     lda CHARSET_ROM + 3 * $FF, x
  74.     jsr flip_bits       ; Flip bits horizontally
  75.     sta CHAR_MEM + 3 * $FF, x
  76.     inx
  77.     bne copy_loop4  ; Continue until X wraps around (256 times)
  78.  
  79. ; Fifth 256 bytes
  80.     ldx #$00   ; Reset X for the outer loop
  81. copy_loop5:
  82.     lda CHARSET_ROM + 4 * $FF, x
  83.     jsr flip_bits       ; Flip bits horizontally
  84.     sta CHAR_MEM + 4 * $FF, x
  85.     inx
  86.     bne copy_loop5  ; Continue until X wraps around (256 times)
  87.  
  88. ; Sixth 256 bytes
  89.     ldx #$00   ; Reset X for the outer loop
  90. copy_loop6:
  91.     lda CHARSET_ROM + 5 * $FF, x
  92.     jsr flip_bits       ; Flip bits horizontally
  93.     sta CHAR_MEM + 5 * $FF, x
  94.     inx
  95.     bne copy_loop6  ; Continue until X wraps around (256 times)
  96.  
  97. ; Using post-indexed indirect addressing
  98. ; Copy flipped character set to buffer for vertical flipping
  99. ldx #<CHAR_MEM    ; Set up source pointer low byte
  100.     stx $FA
  101.     ldx #>CHAR_MEM    ; Set up source pointer high byte
  102.     stx $FB
  103.     ldx #<BUFFER      ; Set up destination pointer low byte
  104.     stx $FC
  105.     ldx #>BUFFER      ; Set up destination pointer high byte
  106.     stx $FD
  107.     ldy #0
  108.  
  109. ciclo:               ; Copy loop for character set
  110.     lda ($FA), y     ; Load byte from source
  111.     sta ($FC), y     ; Store byte in buffer
  112.     iny
  113.     bne ciclo        ; Continue for 256 bytes
  114.     inc $FB          ; Increment high bytes of pointers
  115.     inc $FD
  116.     ldx $FB
  117.     cpx #$35         ; Check if we've copied all characters
  118.     bne ciclo
  119.  
  120. ; Using post-indexed indirect addressing
  121. ; Prepare to flip characters vertically
  122.     ldx #<CHAR_MEM   ; Reset pointers for vertical flip
  123.     stx $FA
  124.     ldx #>CHAR_MEM
  125.     stx $FB
  126.     ldx #<BUFFER
  127.     stx $FC
  128.     ldx #>BUFFER
  129.     stx $FD
  130.  
  131. ; Flip each character vertically (8 bytes per character)
  132. flip_all_chars_loop:
  133.     ldx #7           ; Start from bottom row (7)
  134.     ldy #0           ; Start reading from top row (0)
  135. C1:
  136.     lda ($FC), y     ; Read byte from buffer
  137.     sta $02          ; Store temporarily
  138.     tya              ; Save Y
  139.     pha            
  140.     txa              ; Use X as new Y for inverted write
  141.     tay            
  142.     lda $02          ; Get stored byte
  143.     sta ($FA), y     ; Write to new position
  144.     pla              ; Restore Y
  145.     tay            
  146.     iny              ; Next source byte
  147.     dex              ; Previous destination position
  148.     cpy #8           ; Check if we've done all 8 rows
  149.     bne C1
  150. ; Move to next character in buffer
  151.     clc                 ; Clear carry to ensure correct addition
  152.     lda $FC             ; Load low byte of buffer pointer
  153.     adc #8              ; Move forward by 8 bytes (size of one character)
  154.     sta $FC             ; Store updated low byte
  155.     bcc skip1           ; If no carry, skip incrementing high byte
  156.     inc $FD             ; Otherwise, increment high byte of buffer pointer
  157. skip1:
  158. ; Move to next character in destination
  159.     clc                 ; Clear carry to ensure correct addition
  160.     lda $FA             ; Load low byte of destination pointer
  161.     adc #8              ; Move forward by 8 bytes (size of one character)
  162.     sta $FA             ; Store updated low byte
  163.     bcc skip2           ; If no carry, skip incrementing high byte
  164.     inc $FB             ; Otherwise, increment high byte of destination pointer
  165. skip2:
  166. ; Check if we've processed all characters
  167.     lda $FB
  168.     cmp #$35         ; End of character set
  169.     bne flip_all_chars_loop
  170.  
  171. ; Using post-indexed indirect addressing
  172. ; Copy screen memory to buffer for flipping
  173.     ldx #<INIT_SCREEN
  174.     stx $FA
  175.     ldx #>INIT_SCREEN
  176.     stx $FB
  177.     ldx #<BUFFER
  178.     stx $FC
  179.     ldx #>BUFFER
  180.     stx $FD
  181.     ldy #0
  182. ciclo1:               ; Copy screen memory to buffer
  183.     lda ($FA), y
  184.     sta ($FC), y
  185.     iny
  186.     bne ciclo1
  187.     inc $FB
  188.     inc $FD
  189.     ldx $FB
  190.     cpx #8            ; Check if we've copied all screen memory
  191.     bne ciclo1
  192.  
  193. ; Flip screen memory vertically in four 256-byte blocks
  194.     ldx #$00  
  195.     ldy #$FF
  196. flip_screen_loop:    ; First block
  197.     lda BUFFER, x    ; Read from start of buffer
  198.     sta END_SCREEN - $FF, y  ; Write to end of screen
  199.     inx
  200.     dey
  201.     bne flip_screen_loop
  202.  
  203.     ldx #$00  
  204.     ldy #$FF
  205. flip_screen_loop2:   ; Second block
  206.     lda BUFFER + $FF, x
  207.     sta END_SCREEN - 2 * $FF, y
  208.     inx
  209.     dey
  210.     bne flip_screen_loop2
  211.  
  212.     ldx #$00  
  213.     ldy #$FF
  214. flip_screen_loop3:   ; Third block
  215.     lda BUFFER + 2 * $FF, x
  216.     sta END_SCREEN - 3 * $FF, y
  217.     inx
  218.     dey
  219.     bne flip_screen_loop3
  220.  
  221.     ldx #$00  
  222.     ldy #$FF
  223. flip_screen_loop4:   ; Fourth block
  224.     lda BUFFER + 3 * $FF, x
  225.     sta END_SCREEN - 4 * $FF, y
  226.     inx
  227.     dey
  228.     bne flip_screen_loop4
  229.  
  230. ; Restore ROM and re-enable interrupts
  231.     lda MEM_CONFIG   ; Restore ROM configuration
  232.     ora #$04         ; Set bit 2 to enable ROM
  233.     sta MEM_CONFIG
  234.     cli              ; Re-enable interrupts
  235.  
  236. ; Point VIC-II to new character set
  237.     lda VIC_CR
  238.     and #$F0         ; Clear lower nibble
  239.     ora #$0C         ; Set to point to $3000
  240.     sta VIC_CR
  241.  
  242.     rts              ; Return from subroutine
  243.  
  244. ; Subroutine to flip bits in a byte horizontally
  245. flip_bits:
  246.     tay              ; Use byte as index into lookup table
  247.     lda bit_flip_table, y  ; Get flipped byte from table
  248.     rts
  249.  
  250. ; Lookup table for bit flipping
  251. ; Each byte in the table contains the bit-reversed pattern of its index
  252. ; For example: Input 0000 0001 ($01) returns 1000 0000 ($80)
  253. bit_flip_table:
  254.     .byte $00, $80, $40, $C0, $20, $A0, $60, $E0
  255.     .byte $10, $90, $50, $D0, $30, $B0, $70, $F0
  256.     .byte $08, $88, $48, $C8, $28, $A8, $68, $E8
  257.     .byte $18, $98, $58, $D8, $38, $B8, $78, $F8
  258.     .byte $04, $84, $44, $C4, $24, $A4, $64, $E4
  259.     .byte $14, $94, $54, $D4, $34, $B4, $74, $F4
  260.     .byte $0C, $8C, $4C, $CC, $2C, $AC, $6C, $EC
  261.     .byte $1C, $9C, $5C, $DC, $3C, $BC, $7C, $FC
  262.     .byte $02, $82, $42, $C2, $22, $A2, $62, $E2
  263.     .byte $12, $92, $52, $D2, $32, $B2, $72, $F2
  264.     .byte $0A, $8A, $4A, $CA, $2A, $AA, $6A, $EA
  265.     .byte $1A, $9A, $5A, $DA, $3A, $BA, $7A, $FA
  266.     .byte $06, $86, $46, $C6, $26, $A6, $66, $E6
  267.     .byte $16, $96, $56, $D6, $36, $B6, $76, $F6
  268.     .byte $0E, $8E, $4E, $CE, $2E, $AE, $6E, $EE
  269.     .byte $1E, $9E, $5E, $DE, $3E, $BE, $7E, $FE
  270.     .byte $01, $81, $41, $C1, $21, $A1, $61, $E1
  271.     .byte $11, $91, $51, $D1, $31, $B1, $71, $F1
  272.     .byte $09, $89, $49, $C9, $29, $A9, $69, $E9
  273.     .byte $19, $99, $59, $D9, $39, $B9, $79, $F9
  274.     .byte $05, $85, $45, $C5, $25, $A5, $65, $E5
  275.     .byte $15, $95, $55, $D5, $35, $B5, $75, $F5
  276.     .byte $0D, $8D, $4D, $CD, $2D, $AD, $6D, $ED
  277.     .byte $1D, $9D, $5D, $DD, $3D, $BD, $7D, $FD
  278.     .byte $03, $83, $43, $C3, $23, $A3, $63, $E3
  279.     .byte $13, $93, $53, $D3, $33, $B3, $73, $F3
  280.     .byte $0B, $8B, $4B, $CB, $2B, $AB, $6B, $EB
  281.     .byte $1B, $9B, $5B, $DB, $3B, $BB, $7B, $FB
  282.     .byte $07, $87, $47, $C7, $27, $A7, $67, $E7
  283.     .byte $17, $97, $57, $D7, $37, $B7, $77, $F7
  284.     .byte $0F, $8F, $4F, $CF, $2F, $AF, $6F, $EF
  285.     .byte $1F, $9F, $5F, $DF, $3F, $BF, $7F, $FF
  286.  
  287. message:
  288.     .text "flipscreen by kimono"  ; Null-terminated string
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement