diff --git a/Makefile b/Makefile index b8ec95d..d4fbe6e 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ MACHINE ?= c64 AS=ca65 LD=ld65 -ASFLAGS=--include-dir core -g +ASFLAGS=-g ifeq ($(PROJECT), cartridge) ASFLAGS+=-D CART_FC3=1 @@ -27,31 +27,59 @@ else endif endif -SOURCES=core/header.s core/vectors.s core/init.s core/basic.s core/drive.s core/desktop_helper.s core/speeder.s core/monitor.s core/wrappers.s core/junk.s core/editor.s core/printer.s core/format.s core/freezer.s core/persistent.s +SOURCES_B0=bank0/header.s bank0/vectors.s bank0/init.s bank0/basic.s bank0/drive.s bank0/desktop_helper.s bank0/speeder.s bank0/monitor.s bank0/wrappers.s bank0/editor.s bank0/printer.s bank0/format.s bank0/freezer.s bank0/persistent.s bank0/junk.s +SOURCES_B3=bank3/freezer_entry.s bank3/freezer_reset.s bank3/freezer_game.s bank3/freezer_backup.s bank3/screenshot.s bank3/persistent.s bank3/mysterycode.s bank3/desktop_helper2.s bank3/freezer_menu.s -DEPS=core/kernal.i core/persistent.i +DEPS=core/kernal.i bank0/persistent.i -OBJECTS=$(SOURCES:.s=.o) +OBJECTS_B0=$(SOURCES_B0:.s=.o) +OBJECTS_B3=$(SOURCES_B3:.s=.o) -all: fc3.bin +all: fc3full.crt clean: - rm -f core/*.o projects/monitor/*.o projects/speeder/*.o *.bin *.prg *.hexdump + rm -f bank0/*.o bank3/*.o projects/monitor/*.o projects/speeder/*.o *.bin *.prg *.hexdump fc3full.bin fc3full.crt + make -C bank3/disk_backload clean + make -C bank3/tape_backload clean -test: fc3.bin - @dd if=bin/Final_Cartridge_3_1988-12.bin bs=16384 count=1 2> /dev/null | hexdump -C > fc3-orig.bin.hexdump - @hexdump -C fc3.bin > fc3.bin.hexdump - @diff -u fc3-orig.bin.hexdump fc3.bin.hexdump +bank3/disk_backload/backup_loader.prg: + make -C bank3/disk_backload -fc3.bin: $(OBJECTS) core/fc3.cfg - $(LD) -C core/fc3.cfg $(OBJECTS) -o $@ +bank3/tape_backload/backup_loader.prg: + make -C bank3/tape_backload -monitor.prg: core/monitor.o projects/monitor/monitor_support.o projects/monitor/monitor.cfg - $(LD) -C projects/monitor/monitor.cfg core/monitor.o projects/monitor/monitor_support.o -o $@ -Ln labels.txt +testb0: bank0.bin + @dd if=bin/Final_Cartridge_3_1988-12.bin bs=16384 count=1 2> /dev/null | hexdump -C > fc3b0-orig.bin.hexdump + @hexdump -C bank0.bin > bank0.bin.hexdump + @diff -u fc3b0-orig.bin.hexdump bank0.bin.hexdump -speeder.prg: core/speeder.o projects/speeder/speeder_support.o projects/speeder/speeder.cfg - $(LD) -C projects/speeder/speeder.cfg core/speeder.o projects/speeder/speeder_support.o -o $@ +testb3: bank3.bin + @dd if=bin/Final_Cartridge_3_1988-12.bin bs=16384 skip=3 count=1 2> /dev/null | hexdump -C > fc3b3-orig.bin.hexdump + @hexdump -C bank3.bin > bank3.bin.hexdump + @diff -u fc3b3-orig.bin.hexdump bank3.bin.hexdump + +bank0.bin: $(OBJECTS_B0) bank0/bank0.cfg + $(LD) -mbank0.map -C bank0/bank0.cfg $(OBJECTS_B0) -o $@ + +bank3.bin: $(OBJECTS_B3) bank3/bank3.cfg + $(LD) -mbank3.map -C bank3/bank3.cfg $(OBJECTS_B3) -o $@ + +monitor.prg: bank0/monitor.o projects/monitor/monitor_support.o projects/monitor/monitor.cfg + $(LD) -C projects/monitor/monitor.cfg bank0/monitor.o projects/monitor/monitor_support.o -o $@ -Ln labels.txt + +speeder.prg: bank0/speeder.o projects/speeder/speeder_support.o projects/speeder/speeder.cfg + $(LD) -C projects/speeder/speeder.cfg bank0/speeder.o projects/speeder/speeder_support.o -o $@ %.o: %.s $(DEPS) $(AS) $(ASFLAGS) $< -o $@ +bank3/freezer_backup.o: bank3/freezer_backup.s bank3/disk_backload/backup_loader.prg bank3/tape_backload/backup_loader.prg $(DEPS) + $(AS) $(ASFLAGS) $< -o $@ + +fc3full.bin: bank0.bin bank3.bin + cp bin/Final_Cartridge_3_1988-12.bin fc3full.bin + dd if=bank0.bin of=fc3full.bin bs=16384 count=1 conv=notrunc + dd if=bank3.bin of=fc3full.bin bs=16384 seek=3 count=1 conv=notrunc + +fc3full.crt: fc3full.bin + cartconv -i fc3full.bin -o fc3full.crt -t fc3 diff --git a/README.md b/README.md index f24148e..5b38d2b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,16 @@ +Note: The master branch contains source code for the original Final Cartridge III. The Final Cartridge III 101% source code can be found in the development branch. + # Final Cartridge -This project is the reverse-engineered and documented Commodore 64 cc65/ca65/cl65 assembly source code of the first bank of the "*Final Cartridge III*". +This project is the reverse-engineered and documented Commodore 64 cc65/ca65/cl65 assembly source code of the "*Final Cartridge III*". Currently source code of bank 0 and low part of bank 3 has been reconstructed. -When assembled, the resulting binary is identical with the 1988-12 version of bank 0 of the original cartridge ROM. +When assembled, the resulting binary is identical with the 1988-12 version of the original cartridge ROM. ## What is contained? -Bank 0 contains the BASIC and editor extensions, the floppy and tape speeder, fast format, the centronics printer driver, and the monitor. This project does not contain Desktop, the freezer or the BASIC menu bar. +Bank 0 contains the BASIC and editor extensions, the floppy and tape speeder, fast format, the centronics printer driver, and the monitor. + +Bank 3 contains the freezer. ## Building diff --git a/core/fc3.cfg b/bank0/bank0.cfg similarity index 76% rename from core/fc3.cfg rename to bank0/bank0.cfg index 6c3d5a6..5a73bae 100644 --- a/core/fc3.cfg +++ b/bank0/bank0.cfg @@ -1,18 +1,20 @@ MEMORY { ROM0LO: start = $8000, size = $1E00, fill = yes, fillval = $ff, file = %O; - ROMIO: start = $9E00, size = $0200, fill = yes, fillval = $ff, file = %O; + ROMIO: start = $9E00, size = $01E8, fill = yes, fillval = $ff, file = %O; + ROMIO_BAR_IRQ: start = $9FE8, size = $0018, fill = yes, fillval = $ff, file = %O; ROM0HI: start = $A000, size = $1FA0, fill = yes, fillval = $ff, file = %O; ROM0TOP: start = $BFA0, size = $005A, fill = yes, fillval = $ff, file = %O; ULTIMAX_VECTORS: start = $BFFA, size = $0006, fill = yes, fillval = $ff, file = %O; - L0220: start = $0220, size = $0060; - IO: start = $DE00, size = $0200; - BASIC: start = $0801, size = $97FF; - DRIVE4A: start = $0400, size = $0400; - DRIVE4B: start = $0400, size = $0400; - DRIVE5: start = $0500, size = $0300; - FREEZER: start = $FFA0, size = $005A; - L0100: start = $0100, size = $00FF; + L0220: start = $0220, size = $0060; + IO: start = $DE00, size = $01E8; + IO_BAR_IRQ: start = $DFE8, size = $0018; + BASIC: start = $0801, size = $97FF; + DRIVE4A: start = $0400, size = $0400; + DRIVE4B: start = $0400, size = $0400; + DRIVE5: start = $0500, size = $0300; + FREEZER: start = $FFA0, size = $005A; + L0100: start = $0100, size = $00FF; } SEGMENTS { @@ -35,6 +37,7 @@ SEGMENTS { drive_code_load: load = ROM0LO, run = DRIVE4B, type = ro, define = yes; romio: load = ROMIO, run = IO, type = ro; + romio_bar_irq: load = ROMIO_BAR_IRQ, run = IO_BAR_IRQ, type = ro; basic_vectors: load = ROM0HI, type = ro; printer: load = ROM0HI, type = ro; @@ -53,3 +56,7 @@ SEGMENTS { freezer: load = ROM0TOP, run = FREEZER, type = ro; freezer_vectors: load = ULTIMAX_VECTORS, type = ro; } + +SYMBOLS { + psettings: type=weak, value=$BFFA; +} \ No newline at end of file diff --git a/core/basic.s b/bank0/basic.s similarity index 94% rename from core/basic.s rename to bank0/basic.s index fcffad0..ab3b44e 100644 --- a/core/basic.s +++ b/bank0/basic.s @@ -31,7 +31,7 @@ ; "UNPACK" Command - decompress a program ; "PACK" Command - compress a program -.include "kernal.i" +.include "../core/kernal.i" .include "persistent.i" ; from monitor @@ -114,9 +114,10 @@ new_expression: evaluate_hex_expression: lda #0 ldx #10 -: sta $5D,x +@1: + sta $5D,x dex - bpl :- + bpl @1 L81B9: jsr _CHRGET bcc L81C4 cmp #'A' @@ -134,15 +135,16 @@ L81C4: sbc #$2F L81D6: sta $61 L81D8: pla - jsr _add_A_to_FAC + jsr _add_a_to_fac1 jmp L81B9 L81DF: clc - jmp _disable_rom + jmp _disable_fc3rom -L81E3: lda #$16 +set_bsout_to_screen: + lda #PRT sta $0327 rts @@ -166,7 +168,7 @@ auto_line_number_increment := $0336 new_mainloop: jsr set_irq_and_kbd_handlers jsr cond_init_load_save_vectors - jsr L81E3 + jsr set_bsout_to_screen jsr WA560 stx TXTPTR sty TXTPTR + 1 @@ -183,7 +185,7 @@ new_mainloop: jsr new_tokenize jmp _new_execute -L822B: jsr _get_line_number +L822B: jsr _basic_string_to_word tax bne L8234 sta $02A9 @@ -208,28 +210,33 @@ new_tokenize: ldx TXTPTR ldy #4 sty $0F -L8259: lda $0200,x ; read character from direct mode - bpl L8265 +@loadchar: + lda $0200,x ; read character from direct mode + bpl @notoken cmp #$FF ; PI - beq L82B6 + beq @nextchar inx - bne L8259 -L8265: cmp #' ' - beq L82B6 - sta $08 + bne @loadchar +@notoken: + cmp #' ' + beq @nextchar + sta $08 ; If '"' then '"' is the char that ends skipping cmp #'"' - beq L82DB + beq @skip_til_end bit $0F - bvs L82B6 + bvs @nextchar cmp #'?' - bne L827B + bne @not_print lda #$99 ; PRINT token - bne L82B6 -L827B: cmp #'0' - bcc L8283 - cmp #$3C - bcc L82B6 -L8283: sty $71 + bne @nextchar +@not_print: + cmp #'0' + bcc @punctuation + cmp #'<' + bcc @nextchar +@punctuation: + ; PETSCII characters less than '0', i.e. punctuation characters like @#?,. + sty $71 ; **** this is the same code as BASIC ROM $A579-$A5AD (end) **** stx TXTPTR @@ -237,78 +244,92 @@ L8283: sty $71 sty $22 ldy #>(new_basic_keywords - 1) sty $23 -L828F: ldy #0 +@zero_token: + ldy #0 ; Start at token 0 sty $0B dex -L8294: inx +@incptr_cmpchar: + inx inc $22 - bne L829B + bne @cmpchar inc $23 -L829B: lda $0200,x +@cmpchar: + lda $0200,x sec sbc ($22),y - beq L8294 + beq @incptr_cmpchar cmp #$80 - bne L82E2 + bne @char_nomatch ldy $23 - cpy #$A9 - bcs L82B2 + cpy #$A9 ; $22/$23 pointing to original token table? + bcs :+ lda $0B - adc #$CC + adc #$CC ; Final Cartridge III tokens start at $CC .byte $2C -L82B2: ora $0B -L82B4: ldy $71 - +: ora $0B +@maybe_skip: + ldy $71 ; **** this is the same code as BASIC ROM $A5C9-$A5F8 (start) **** -L82B6: inx +@nextchar: + inx iny - sta $01FB,y - lda $01FB,y - beq L830B + sta $0200 - 5,y + lda $0200 - 5,y + beq @done sec - sbc #$3A - beq L82C9 - cmp #$49 - bne L82CB -L82C9: sta $0F -L82CB: sec - sbc #$55 - bne L8259 + sbc #':' ; Is it a ":" ? + beq @colon_or_data + cmp #$83-':' ; Is it a DATA token? + bne @nor_colon_nor_data +@colon_or_data: + sta $0F +@nor_colon_nor_data: + sec + sbc #$8f-':' ; Is it a REM token ? + bne @loadchar + ; REM token, no further tokenizaton until end of line sta $08 -L82D2: lda $0200,x - beq L82B6 - cmp $08 - beq L82B6 -L82DB: iny - sta $01FB,y +@loadskip: + lda $0200,x + beq @nextchar + cmp $08 ; Value in $08 = char that stops skipping + beq @nextchar +@skip_til_end: + iny + sta $0200 - 5,y inx - bne L82D2 -L82E2: ldx TXTPTR - inc $0B + bne @loadskip +@char_nomatch: + ldx TXTPTR + inc $0B ; increase token ; **** this is the same code as BASIC ROM $A5C9-$A5F8 (end) **** -L82E6: lda ($22),y + ; Move the token pointer to the next token +@tokenptr_nexttoken: + lda ($22),y ; Load current char of token php - inc $22 - bne L82EF - inc $23 -L82EF: plp - bpl L82E6 + inc $22 ; Inc token pointer low byte + bne :+ + inc $23 ; Inc token pointer high byte +: plp + bpl @tokenptr_nexttoken lda ($22),y - bne L829B - lda $23 + bne @cmpchar + ; End of token table + lda $23 ; $22/$23 pointing to original token table? cmp #$A9 - bcs L8306 - lda #$A9 + bcs @get_next_char + lda #>(basic_keywords - 1) sta $23 - lda #$FF + lda #<(basic_keywords - 1) sta $22 - bne L828F ; always + bne @zero_token ; always ; **** this is the same code as BASIC ROM $A604-$A612 (start) **** -L8306: lda $0200,x - bpl L82B4 -L830B: sta $01FD,y +@get_next_char: + lda $0200,x + bpl @maybe_skip +@done: sta $01FD,y dec TXTPTR + 1 lda #$FF sta TXTPTR @@ -340,7 +361,7 @@ L832F: cmp #$E9 ; last new token + 1 pha jmp _CHRGET -L8342: jmp _disable_rom +L8342: jmp _disable_fc3rom trace_command: lda PNTR ; save cursor state @@ -659,7 +680,7 @@ L8531: php stx $5F : rts -L858E: jsr _get_line_number +L858E: jsr _basic_string_to_word lda $14 sta auto_current_line_number,y iny @@ -668,7 +689,7 @@ L858E: jsr _get_line_number iny jmp _CHRGOT -L85A0: jsr _get_line_number +L85A0: jsr _basic_string_to_word ldx $14 stx $AC,y ldx $15 @@ -970,7 +991,7 @@ L87F7: cmp L8603,x bpl L87F7 jsr _CHRGOT bcs L87D4 - jsr _get_line_number + jsr _basic_string_to_word lda $15 ldy $14 jsr L8FF9 @@ -1390,7 +1411,7 @@ get_secaddr_and_send_listen: bne :+ jsr _CHRGET bcs L8B3A ; SYNTAX ERROR - jsr _get_line_number + jsr _basic_string_to_word lda $15 bne L8B3A ; must be < 256, otherwise SYNTAX ERROR lda $14 @@ -1547,7 +1568,7 @@ L8C03: lda $028D bne L8C03 ; wait while CBM key is pressed txa jsr do_detokenize - jmp _list + jmp _list_print_non_token_byte do_detokenize: cmp #$E9 @@ -1659,7 +1680,7 @@ L8CB6: sta $22 L8CCE: tya bmi L8CD7 - jsr _int_to_fac + jsr _int_to_fac1 jmp L8CDA L8CD7: jsr L8D21 @@ -1702,7 +1723,7 @@ L8D12: ldy #0 jsr _lda_22_indy tay txa - jmp _ay_to_float + jmp _ay_to_fac1 L8D21: jsr L8D0D ldy #2 @@ -1819,7 +1840,7 @@ L8DCC: jsr _basic_bsout L8E02: iny jsr _lda_5f_indy bmi L8E0F - jsr _int_to_fac + jsr _int_to_fac1 lda #5 bne L8E14 L8E0F: jsr L8D21 @@ -2105,7 +2126,7 @@ L901D: lda alt_pack_run,x pha lda #<(unpack_entry - 1) pha - jmp _disable_rom + jmp _disable_fc3rom alt_pack_run: jsr $A663 ; CLR diff --git a/core/desktop_helper.s b/bank0/desktop_helper.s similarity index 98% rename from core/desktop_helper.s rename to bank0/desktop_helper.s index de90c43..edc31ab 100644 --- a/core/desktop_helper.s +++ b/bank0/desktop_helper.s @@ -5,7 +5,7 @@ ; this library code using cross-bank calls. It also calls this to ; start a program in BASIC mode. -.include "kernal.i" +.include "../core/kernal.i" .include "persistent.i" ; from basic @@ -252,9 +252,9 @@ L968C: ldy $AE rts disk_operation_fallback: - lda #<($FF92 - 1) + lda #>($9200 - 1) pha - lda #>($FF92 - 1) ; ??? + lda #<($9200 - 1) pha lda #$43 jmp _jmp_bank ; bank 3 diff --git a/core/drive.s b/bank0/drive.s similarity index 98% rename from core/drive.s rename to bank0/drive.s index 8af6cf8..cde7b47 100644 --- a/core/drive.s +++ b/bank0/drive.s @@ -3,7 +3,7 @@ ; ---------------------------------------------------------------- ; The BASIC extension and fast format call into this. -.include "kernal.i" +.include "../core/kernal.i" ; from wrapper .import disable_rom_jmp_error diff --git a/core/editor.s b/bank0/editor.s similarity index 99% rename from core/editor.s rename to bank0/editor.s index 89291a1..8f582d6 100644 --- a/core/editor.s +++ b/bank0/editor.s @@ -9,7 +9,7 @@ ; * auto-scrolling of BASIC programs: when the screen scrolls ; either direction, a new BASIC line is LISTed -.include "kernal.i" +.include "../core/kernal.i" .include "persistent.i" ; from basic @@ -69,7 +69,7 @@ L926A: cmp #CR ; CTRL + CR: print screen L927C: jmp _evaluate_modifier -L927F: jmp _disable_rom +L927F: jmp _disable_fc3rom L9282: cmp #$11 ; DOWN beq L92DD diff --git a/core/format.s b/bank0/format.s similarity index 99% rename from core/format.s rename to bank0/format.s index 6cd968c..58ca014 100644 --- a/core/format.s +++ b/bank0/format.s @@ -2,7 +2,7 @@ ; Fast Format ; ---------------------------------------------------------------- -.include "kernal.i" +.include "../core/kernal.i" ; from drive .import check_iec_error diff --git a/core/freezer.s b/bank0/freezer.s similarity index 63% rename from core/freezer.s rename to bank0/freezer.s index 4615f30..076b69d 100644 --- a/core/freezer.s +++ b/bank0/freezer.s @@ -10,9 +10,15 @@ ; jumps to a different bank. .include "persistent.i" +.include "../core/fc3ioreg.i" .segment "freezer" +; +; The freeze NMI handler exists identical in bank 0 and bank 3 +; at the same memory location. Execution starts in bank 0, then +; continues in bank 3. +; freezer: sei pha @@ -25,8 +31,13 @@ freezer: pha lda #$37 sta $01 ; processor port defaut value - lda #$13 - sta $DFFF ; NMI = 1, GAME = 1, EXROM = 0 + + ; Activate Ultimax mode and bank 3, NMI line stays active + lda #fcio_bank_3|fcio_c64_ultimaxmode + sta fcio_reg ; NMI = 1, GAME = 1, EXROM = 0 + + ; From now on, we are in bank 3 + lda $DC0B ; CIA 1 TOD hours lda $DD0B ; CIA 2 TOD hours (???) txa @@ -49,8 +60,17 @@ LBFC7: lda $02,x ; copy $02 - $0C onto stack sta $DD0F ; disable CIA 2 Timer B lda #$7C sta $DD0D ; disable some NMIs? (???) - ldx #3 - jmp LDFE0 ; ??? + + ; Note: Bank3 is active. Note that the IOROM at $DE00..$DFFF is also affected by bank + ; switching. The IOROM of Bank3 is different than that of bank 0 (code persistent.s) + ldx #fcio_bank_3 | fcio_c64_16kcrtmode ; NMI line stays active + jmp $DFE0 + + ; The code at $DFE0 of bank 3 (also at offset $DFE0 in FC3 ROM image) that follows is: + ; + ; 9FE0 8E FF DF STX $DFFF (fcio_reg) + ; 9FE3 8D 0D DD STA $DD0D + ; 9FE6 4C 00 80 JMP $8000 .segment "freezer_vectors" diff --git a/core/header.s b/bank0/header.s similarity index 100% rename from core/header.s rename to bank0/header.s diff --git a/core/init.s b/bank0/init.s similarity index 76% rename from core/init.s rename to bank0/init.s index 2415390..2b863b3 100644 --- a/core/init.s +++ b/bank0/init.s @@ -2,7 +2,7 @@ ; BASIC Extension and Speeder Initialization ; ---------------------------------------------------------------- -.include "kernal.i" +.include "../core/kernal.i" .include "persistent.i" ; from basic @@ -11,9 +11,12 @@ ; from printer .import set_io_vectors_with_hidden_rom +; from bank 2 +.import psettings + .global entry .global init_load_and_basic_vectors -.global init_vectors_jmp_bank_2 +.global init_vectors_goto_psettings .global init_basic_vectors .global go_desktop .global go_basic @@ -26,9 +29,14 @@ LBFFA := $BFFA .segment "basic_init" -; ??? unused? +; +; This is called from the freezer to perform the PSET command +; + +.export pset +pset: jsr set_io_vectors_with_hidden_rom - lda #$43 ; bank 2 + lda #$43 ; bank 3 jmp _jmp_bank init_load_and_basic_vectors: @@ -41,12 +49,13 @@ L8031: lda basic_vectors,x ; overwrite BASIC vectors bpl L8031 rts -init_vectors_jmp_bank_2: +init_vectors_goto_psettings: + ; Show the printer settings window (code in bank 2) jsr init_load_save_vectors jsr init_basic_vectors - lda #>(LBFFA - 1) + lda #>(psettings - 1) pha - lda #<(LBFFA - 1) ; ??? + lda #<(psettings - 1) pha lda #$42 ; bank 2 jmp _jmp_bank @@ -82,22 +91,28 @@ L805A: sta $02,y jsr init_load_and_basic_vectors cli pla ; $ D - tax + tax ; X = $DC01 value pla - cpx #$7F ; $DC01 value + cpx #$7F ; runstop pressed? beq L80C4 ; 1988-13 changes this to "bne" to start into BASIC - cpx #$DF - beq go_desktop - and #$7F + cpx #$DF ; C= pressed? beq go_desktop + ; This determines which is default at power-on: Desktop or BASIC + and #$7F ; Was the VIC-II not initialized at reset?? + beq go_desktop ; Boot DESKTOP by default + ; If the VIC-II was initalized... check wether the desktop signature + ; is in memory, if yes, boot into desktop. ldy #mg87_signature_end - mg87_signature - 1 -L809D: lda $CFFC,y +: lda $CFFC,y cmp mg87_signature,y bne L80AA dey - bpl L809D + bpl :- bmi go_desktop ; MG87 found -L80AA: jmp ($A000) +L80AA: ; Note we are still in 16K cartridge mode. This boots into BASIC thanks to + ; the basic_vectors segment in basic.s, which is located at $A000 in cartridge + ; ROM. + jmp ($A000) ; Boot into BASIC mg87_signature: .byte "MG87" @@ -126,7 +141,7 @@ go_basic: pha lda #<($E397 - 1) ; BASIC start pha - jmp _disable_rom + jmp _disable_fc3rom load_save_vectors: .addr _new_load ; $0330 LOAD @@ -157,7 +172,7 @@ L80FE: lda load_save_vectors,y ; overwrite LOAD and SAVE vectors sta $0330,y dey bpl L80FE - lda $02A6 + lda $02A6 ; PAL or NTSC? beq L810F - inc $0330 + inc $0330 ; For PAL machines, $0330/$0331 points to $DE21. L810F: rts diff --git a/core/junk.s b/bank0/junk.s similarity index 100% rename from core/junk.s rename to bank0/junk.s diff --git a/core/monitor.s b/bank0/monitor.s similarity index 99% rename from core/monitor.s rename to bank0/monitor.s index 6a638b1..e8e6f5b 100644 --- a/core/monitor.s +++ b/bank0/monitor.s @@ -37,7 +37,7 @@ ; * "OD" switches all memory dumps/input to the drive's memory. ; * "B" command to introspect cartridge ROM -.include "kernal.i" +.include "../core/kernal.i" .ifdef CART_FC3 .include "persistent.i" @@ -191,7 +191,7 @@ enable_all_roms: goto_user: .ifdef CART_FC3 - jsr _disable_rom + jsr _disable_fc3rom .endif .ifdef MACHINE_C64 sta R6510 @@ -1580,9 +1580,9 @@ LB40A: bne LB3F0 LB42D: .ifdef CART_FC3 - lda #>(_enable_rom - 1) + lda #>(_enable_fcbank0 - 1) pha - lda #<(_enable_rom - 1) + lda #<(_enable_fcbank0 - 1) pha .endif lda #0 @@ -1590,9 +1590,9 @@ LB42D: LB438: .ifdef CART_FC3 - lda #>(_enable_rom - 1) + lda #>(_enable_fcbank0 - 1) pha - lda #<(_enable_rom - 1) + lda #<(_enable_fcbank0 - 1) pha .endif lda #zp1 ; pointer to ZP location with address diff --git a/core/persistent.i b/bank0/persistent.i similarity index 81% rename from core/persistent.i rename to bank0/persistent.i index fa6dc2f..929107e 100644 --- a/core/persistent.i +++ b/bank0/persistent.i @@ -1,22 +1,22 @@ .import LDFE0 .import _CHRGET .import _CHRGOT -.import _add_A_to_FAC -.import _ay_to_float +.import _add_a_to_fac1 +.import _ay_to_fac1 .import _basic_bsout +.import _basic_string_to_word .import _basic_warm_start .import _check_for_stop -.import _disable_rom -.import _disable_rom_set_01 -.import _enable_rom +.import _disable_fc3rom +.import _disable_fc3rom_set_01 +.import _enable_fcbank0 .import _evaluate_modifier .import _execute_statement .import _expression_cont .import _get_filename .import _get_int -.import _get_line_number .import _int_to_ascii -.import _int_to_fac +.import _int_to_fac1 .import _jmp_bank .import _kbd_handler .import _lda_22_indy @@ -26,7 +26,7 @@ .import _lda_TXTPTR_indy .import _lda_8b_indy .import _lda_ae_indx -.import _list +.import _list_print_non_token_byte .import _load_ac_indy .import _load_FNADR_indy .import _new_bsout diff --git a/bank0/persistent.s b/bank0/persistent.s new file mode 100644 index 0000000..57b55b2 --- /dev/null +++ b/bank0/persistent.s @@ -0,0 +1,485 @@ +; ---------------------------------------------------------------- +; I/O Area ROM +; ---------------------------------------------------------------- +; This is a max. 512 byte section that lives at $1E00-$1FFF of +; bank 0 of the ROM, and will also be mapped into the I/O extension +; area at $DE00-$DFFF, so it's always visible. +; It mostly contains wrappers around BASIC, KERNAL or cartridge +; functions that switch the ROM config in addition. + +.include "../core/kernal.i" +.include "../core/fc3ioreg.i" + +; from printer +.import new_clrch +.import new_clall +.import new_bsout +.import new_ckout + +; from basic +.import reset_warmstart +.import new_tokenize +.import new_execute +.import new_expression +.import new_detokenize +.import new_mainloop + +; from editor +.import kbd_handler + +; from wrapper +.import disable_rom_then_warm_start + +; from speeder +.import new_save +.import new_load + +; from desktop_helper +.import load_and_run_program + +chrget = $0073 +basic_relink = $A533 +basic_search_line = $A613 +basic_set_TXTPTR_to_TXTTAB = $A68E +basic_list_print_non_token_byte =$A6F3 +basic_detokenize = $A724 +basic_execute_next_statement = $A7AE +basic_continue_execute = $A7EF +basic_check_stop = $A82C +basic_string_to_word = $A96B +basic_print_char = $AB47 +basic_continue_arithmic_element= $AE8D +basic_floatptr22_to_fac1 = $BBA6 +basic_add_a_to_fac1 = $BD7E ; Add a as signed integer to float accu +basic_LINPRT = $BDCD ; Print 16 bit number in AX +basic_FRMNUM = $AD8A +basic_GETADR = $B7F7 +basic_ay_to_fac1 = $B395 +kernal_get_filename = $E257 +kernal_basic_warmstart = $E37B ; Kernal basic warm start entry +kernel_print_startup_messages = $E422 +kernel_keyboard_handler = $EB42 +kernal_check_modifier_keys = $EB48 + +.segment "romio" + +LDE00: .byte $40 + +; +; Jump into a bank of the FC3 ROM +; +; Jumps to a routine in the FC3 ROM of which the address is on the stack +; and the bank number in A. +; + +.global _jmp_bank +_jmp_bank: + sta fcio_reg + rts + +; +; Makes bank 0 of the FC3 ROM visible at $8000..$AFFF +; + +.global _enable_fcbank0 +_enable_fcbank0: ; $DE05 + pha + lda #fcio_bank_0|fcio_c64_16kcrtmode|fcio_nmi_line +a_to_fcio_pla: + sta fcio_reg + pla + rts + +; +; _disable_fc3rom: Hides the FC3 ROMS from memory +; _disable_fc3rom_set_01: Stores Y into $01 and hides the FC3 ROMS from memory +; + +.global _disable_fc3rom_set_01 +_disable_fc3rom_set_01:; $DE0D + sty $01 +.global _disable_fc3rom +_disable_fc3rom: ; $DE0F + pha + lda #fcio_bank_0|fcio_c64_crtrom_off|fcio_nmi_line + bne a_to_fcio_pla ; always taken + + +; +; Disable the FC3 ROMS and jump to the basic warm start +; + +.global _basic_warm_start +_basic_warm_start: ; $DE14 + jsr _disable_fc3rom + jmp kernal_basic_warmstart + +enable_all_roms: + ora #$07 + sta $01 + bne _enable_fcbank0 ; always taken + + +; +; KERNAL LOAD routine. Vector $330/$331 points here (ROM original at $F4A5) +; + +.global _new_load +_new_load: ; $DE20 + ; The least significant bit of $0330 indicates wether to use PAL or NTSC timing. + ; This double tay simply handles that the vector may point to either $DE20 or + ; $DE21. Deeper into the load code, in receive_4_bytes, the bit is tested and + ; appropriate timing for PAL and NTSC is chosen. + tay + tay + lda $01 + pha + jsr enable_all_roms + jsr new_load + ; common for load/save +pull_to_cpuport_fcromoff: + tax + pla + sta $01 + txa + ldx $AE + jmp _disable_fc3rom + +; +; KERNAL SAVE routine. Vector $330/$331 points here (ROM original at $F5ED) +; + +.global _new_save +_new_save: ; $DE35 + lda $01 + pha + jsr enable_all_roms + jsr new_save + jmp pull_to_cpuport_fcromoff + +; +; BASIC idle loop. Vector $302/303 points here (ROM original at $A483) +; + +.global _new_mainloop +_new_mainloop: ; $DE41 + lda $01 + jsr enable_all_roms + jmp new_mainloop + +; +; BASIC token decoder. Vector $306/307 points here (ROM original at $A71A) +; + +.global _new_detokenize +_new_detokenize: ; $DE49 + jsr _enable_fcbank0 + jmp new_detokenize + +; +; BASIC read expression next item. Vector $30A/30B points here (ROM original at $AE86) +; + +.global _new_expression +_new_expression: ; $DE4F + jsr _enable_fcbank0 + jmp new_expression + +; +; Keyboard handler. Vector $28F/290 sometimes points here by the BASIC menu bar code +; (ROM original at $EB487) +; + +.global _kbd_handler +_kbd_handler: + lda $02A7 + beq @1 + jmp kernel_keyboard_handler ; LDA #$7F : STA $DC00 : RTS + +@1: lda $A000 + jmp kbd_handler_part2 + +.global _load_ac_indy +_load_ac_indy: ; $DE63 + sta $01 + lda ($AC),y + inc $01 + inc $01 + rts + +.global _load_FNADR_indy +_load_FNADR_indy: ; $DE6C + dec $01 + lda (FNADR),y + inc $01 + rts + +; +; BASIC execute statement. Vector $308/$309 points here (ROM original at $A7E4) +; + +.global _new_execute +_new_execute: ; $DE73 + jsr _CHRGET + jsr new_execute + jsr _disable_fc3rom + jmp basic_execute_next_statement + +; +; new_execute an jump here +; + +.global _execute_statement +_execute_statement: ; $DE7F + jsr _disable_fc3rom + jmp basic_continue_execute + +.global _add_a_to_fac1 +_add_a_to_fac1: ; $DE85 + jsr _disable_fc3rom + jsr basic_add_a_to_fac1 + jmp _enable_fcbank0 + +.global _expression_cont +_expression_cont: ; $DE8E + jsr _disable_fc3rom + jmp basic_continue_arithmic_element + +.global _get_int +_get_int: ; $DE94 + jsr _disable_fc3rom + jsr basic_FRMNUM ; FRMNUM eval expression, make sure it's numeric + jsr basic_GETADR ; GETADR convert FAC into 16 bit int + jmp _enable_fcbank0 + +.global _new_warmstart +_new_warmstart: + jsr _enable_fcbank0 + jsr reset_warmstart + jmp disable_rom_then_warm_start + +.global _evaluate_modifier +_evaluate_modifier: ; $DEA9 + jsr _disable_fc3rom + jmp kernal_check_modifier_keys ; evaluate SHIFT/CTRL/C= + +.global _basic_string_to_word +_basic_string_to_word: ; $DEAF + jsr _disable_fc3rom + jsr basic_string_to_word + jmp _enable_fcbank0 + +.global _basic_bsout +_basic_bsout: ; $DEB8 + jsr _disable_fc3rom + jsr basic_print_char + jmp _enable_fcbank0 + +.global _set_txtptr_to_start +_set_txtptr_to_start: ; $DEC1 + jsr _disable_fc3rom + jsr basic_set_TXTPTR_to_TXTTAB ; set TXTPTR to start of program + jmp _enable_fcbank0 + +.global _check_for_stop +_check_for_stop: ; $DECA + jsr _disable_fc3rom + jsr basic_check_stop ; check for RUN/STOP + jmp _enable_fcbank0 + +.global _relink +_relink: ; $DED3 + jsr _disable_fc3rom + jsr basic_relink ; rebuild BASIC line chaining + beq LDEE1 ; branch always? + +.global _get_filename +_get_filename: ; $DEDB + jsr _disable_fc3rom + jsr kernal_get_filename ; get string from BASIC line, set filename +LDEE1: jmp _enable_fcbank0 + +.global _int_to_ascii +_int_to_ascii: ; $DEE4 + jsr _disable_fc3rom + jsr $BC49 ; FLOAT UNSIGNED VALUE IN FAC+1,2 + jsr $BDDD ; convert FAC to ASCII + jmp _enable_fcbank0 + +.global _ay_to_fac1 +_ay_to_fac1: ; $DEF0 + jsr _disable_fc3rom + jsr basic_ay_to_fac1 + jmp LDEFF + +.global _int_to_fac1 +_int_to_fac1: ; $DEF9 + jsr _disable_fc3rom + jsr $BBA6 ; convert $22/$23 to FAC +LDEFF: iny + jsr $BDD7 ; print FAC + jmp _enable_fcbank0 + + +.global _print_ax_int +_print_ax_int: ; $DF06 + jsr _disable_fc3rom + jsr basic_LINPRT ; LINPRT print A/X as integer + jmp _enable_fcbank0 + +.global _search_for_line +_search_for_line: ; $DF0F + jsr _disable_fc3rom + jsr basic_search_line + php + jsr _enable_fcbank0 + plp + rts + +.global _CHRGET +_CHRGET: ; $DF1B + jsr _disable_fc3rom + jsr CHRGET +LDF21: php + jsr _enable_fcbank0 + plp + rts + +.global _CHRGOT +_CHRGOT: ; $DF27 + jsr _disable_fc3rom + jsr CHRGOT + jmp LDF21 + +.global _lda_5a_indy +_lda_5a_indy: ; $DF30 + jsr _disable_fc3rom + lda ($5A),y + jmp _enable_fcbank0 + +.global _lda_5f_indy +_lda_5f_indy: ; $DF38 + jsr _disable_fc3rom + lda ($5F),y + jmp _enable_fcbank0 + +.global _lda_ae_indx +_lda_ae_indx: ; $DF40 + jsr _disable_fc3rom + lda ($AE,x) + jmp _enable_fcbank0 + +.global _lda_TXTPTR_indy +_lda_TXTPTR_indy: ; $DF48 + jsr _disable_fc3rom + lda (TXTPTR),y + jmp _enable_fcbank0 + +.global _lda_TXTPTR_indx +_lda_TXTPTR_indx: ; DF50 + jsr _disable_fc3rom + lda (TXTPTR,x) + jmp _enable_fcbank0 + +.global _lda_22_indy +_lda_22_indy: ; $DF58 + jsr _disable_fc3rom + lda ($22),y + jmp _enable_fcbank0 + +.global _lda_8b_indy +_lda_8b_indy: ; $DF60 + jsr _disable_fc3rom + lda ($8B),y + jmp _enable_fcbank0 + +_detokenize: ; $DF68 + jsr _disable_fc3rom + jmp basic_detokenize ; detokenize + +.global _list_print_non_token_byte +_list_print_non_token_byte: ; $DF6E + jsr _disable_fc3rom + jmp basic_list_print_non_token_byte ; part of LIST + +.global _print_banner_load_and_run +_print_banner_load_and_run: ; $DF74 + jsr _disable_fc3rom + jsr kernel_print_startup_messages ; print c64 banner + jsr _enable_fcbank0 + jmp load_and_run_program + +kbd_handler_part2: + cmp #$94 ; contents of $A000 in BASIC ROM + bne @1 ; BASIC ROM not visible + jsr _enable_fcbank0 + jmp kbd_handler + +@1: jmp kernal_check_modifier_keys ; default kdb vector + +.global _new_tokenize +_new_tokenize: ; $DF8D + jsr _enable_fcbank0 + jsr new_tokenize + jmp _disable_fc3rom + +;padding + .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + .byte $FF,$FF + +; calls into banks 0+1 +.global _new_ckout +_new_ckout: ; $DFC0 + jsr _enable_fcbank0 + jsr new_ckout + jmp _disable_fc3rom + +.global _new_bsout +_new_bsout: ; $DFC9 + jsr _enable_fcbank0 + jmp new_bsout + +.global _new_clall +_new_clall: ; $DFCF + jsr _enable_fcbank0 + jmp new_clall + +.global _new_clrch +_new_clrch: ; $DFD5 + jsr _enable_fcbank0 + jmp new_clrch + + +;$DFE0 +; +;Note: Freeze handler does not jump here to $DFE0, because it activates bank 3 of the ROM, +;and thus jumps to $DFE0 of bank 3. The ROM contents of bank 3 are different. +; + +.segment "romio_bar_irq" + + sei + lda #$42 ; bank 2 (Desktop, Freezer/Print) + sta fcio_reg +.global _bar_irq +_bar_irq: + lda LDE00 ; $40 ??? + pha + lda $A000 ; ??? + pha + lda #$41 ; bank 1 (Notepad, BASIC (Menu Bar)) + sta fcio_reg + +.global _a_colon_asterisk +_a_colon_asterisk: + .byte ':','*' +.global _a_colon_asterisk_end +_a_colon_asterisk_end: + +; ---------------------------------------------------------------- +; I/O Area ROM End +; ---------------------------------------------------------------- diff --git a/core/printer.s b/bank0/printer.s similarity index 99% rename from core/printer.s rename to bank0/printer.s index 1cb6b72..345c379 100644 --- a/core/printer.s +++ b/bank0/printer.s @@ -4,7 +4,7 @@ ; This hooks CKOUT, BSOUT, CLRCH and CLALL to support Centronics ; and RS-232 printers as device #4. -.include "kernal.i" +.include "../core/kernal.i" .include "persistent.i" .global set_io_vectors_with_hidden_rom @@ -230,7 +230,7 @@ LA19B: rts new_bsout: jsr new_bsout2 - jmp _disable_rom + jmp _disable_fc3rom new_bsout2: pha @@ -256,11 +256,11 @@ LA1C0: lda $95 new_clall: jsr new_clall2 - jmp _disable_rom + jmp _disable_fc3rom new_clrch: jsr new_clrch2 - jmp _disable_rom + jmp _disable_fc3rom new_clall2: lda #0 diff --git a/core/speeder.s b/bank0/speeder.s similarity index 66% rename from core/speeder.s rename to bank0/speeder.s index 84f814d..1c07d19 100644 --- a/core/speeder.s +++ b/bank0/speeder.s @@ -3,7 +3,7 @@ ; ---------------------------------------------------------------- ; This speeds up LOAD and SAVE on both disk and tape -.include "kernal.i" +.include "../core/kernal.i" .include "persistent.i" .global new_load @@ -20,20 +20,20 @@ new_save: send_byte: pha - : bit $DD00 - bpl :- +@1: bit $DD00 ; Wait until DATA IN high + bpl @1 lsr a lsr a lsr a lsr a tax -: lda $D012 +@2: lda $D012 cmp #$31 - bcc :+ + bcc @3 and #$06 cmp #$02 - beq :- -: lda #$07 + beq @2 +@3: lda #$07 sta $DD00 lda iec_tab,x nop @@ -65,15 +65,18 @@ iec_tab: .assert >* = >iec_tab, error, "Page boundary!" receive_4_bytes: - lda $0330 + ; Note $DD00 is set to 0 before this routine is called + ; PAL/NTSC check. Vector points to _new_load for NTSC, _new_load+1 for PAL + lda $0330 cmp #<_new_load - beq L998B -: bit $DD00 - bvs :- + beq @ntsc + ; PAL +@pal: bit $DD00 ; Wait until clock in low + bvs @pal ldy #3 nop ldx $01 -: lda $DD00 +@1: lda $DD00 lsr a lsr a nop @@ -91,16 +94,17 @@ receive_4_bytes: ora $DD00 sta $C1,y dey - bpl :- -.assert >* = >:-, error, "Page boundary!" + bpl @1 +.assert >* = >@pal, error, "Page boundary!" rts -L998B: bit $DD00 - bvs L998B +@ntsc: ; NTSC + bit $DD00 + bvs @ntsc ldy #3 nop ldx $01 -L9995: lda $DD00 +@2: lda $DD00 lsr a lsr a nop @@ -119,22 +123,23 @@ L9995: lda $DD00 ora $DD00 sta $C1,y dey - bpl L9995 + bpl @2 +.assert >* = >@ntsc, error, "Page boundary!" rts -.assert >* = >L998B, error, "Page boundary!" ; *** tape L99B5: tax - beq L99C3 + beq @1 ; LOAD? Then do not install stack code. ldx #$16 : lda L9A50,x sta L0110,x dex bpl :- -L99C3: jmp LA851 +@1: jmp tape_load_code ; *** tape -L99C6: jmp $F530 ; IEC LOAD - used in the error case +iec_load: + jmp $F530 ; IEC LOAD - used in the error case L99C9: pla pla @@ -144,7 +149,7 @@ L99C9: pla pha lda #$A6 pha - jmp _disable_rom_set_01 + jmp _disable_fc3rom_set_01 L99D6: pla pla @@ -154,7 +159,7 @@ L99D6: pla pha lda #$F2 pha - jmp _disable_rom_set_01 + jmp _disable_fc3rom_set_01 new_load2: sty $93 @@ -188,7 +193,7 @@ new_load2: lda ST lsr a lsr a - bcs L99C6 + bcs iec_load jsr $EE13 ; IECIN sta $AF txa @@ -234,20 +239,22 @@ L9A50: lda #$0C L9A67: jmp $F636 ; LDA #0 : SEC : RTS -L9A6A: jmp $F5ED ; default SAVE vector +original_save: + jmp $F5ED ; execute original SAVE routine -L9A6D: jmp $A7C6 ; interpreter loop +turbotape_save: + jmp new_save_tape ; tape turbo new_save2: lda FA cmp #7 - beq L9A6D ; tape turbo - cmp #8 - bcc L9A6A ; not a drive + beq turbotape_save +@1: cmp #8 ; if <8 then not a drive + bcc original_save cmp #10 - bcs L9A6A ; not a drive (XXX why only support drives 8 and 9?) - ldy $B7 - beq L9A6A + bcs original_save ; not a drive (XXX why only support drives 8 and 9?) + ldy $B7 ; length of filename + beq original_save lda #$61 sta SA jsr LA71B @@ -265,23 +272,24 @@ new_save2: dec $AD L9AA3: jsr L9AD0 lda $C1 - jsr L9AC7 + jsr send_byte_and_increment lda $C2 - jsr L9AC7 -L9AB0: lda #$35 + jsr send_byte_and_increment +@3: lda #$35 jsr _load_ac_indy - jsr L9AC7 - bne L9AB0 + jsr send_byte_and_increment + bne @3 lda $A4 bmi L9AC4 jsr L9AD0 - jmp L9AB0 + jmp @3 L9AC4: cli clc rts -L9AC7: jsr send_byte +send_byte_and_increment: + jsr send_byte jsr $FCDB ; inc $AC/$AD dec $93 rts @@ -315,9 +323,9 @@ L9AF0: jsr UNTALK ldy #>__drive_code_load_LOAD__ ldx #>__drive_code_load_RUN__ ; $0400 jsr transfer_code_to_drive - lda #L059A + lda #>drivecode_load_initialize jsr IECOUT jsr UNLSTN sei @@ -343,8 +351,8 @@ L9AF0: jsr UNTALK lda $AF sbc #0 sta $A3 -L9B3D: bit $DD00 - bmi L9B82 +@back: bit $DD00 ; DATA IN high? + bmi @recv ; Then receive data cli php lda $95 @@ -368,22 +376,22 @@ L9B3D: bit $DD00 jsr LA612 jsr UNLSTN plp - bvs L9B78 ; used to be "bcs" in 1988-05 + bvs @done ; used to be "bcs" in 1988-05 lda #$1D sec rts -L9B78: lda #$40 +@done: lda #$40 sta ST jsr LA694 jmp $F5A9 ; LOAD done -L9B82: bvs L9B3D - lda #$20 +@recv: bvs @back ; CLOCK IN high? Then back + lda #$20 ; DATA OUT high, CLOCK OUT 0 sta $DD00 -: bit $DD00 - bvc :- - lda #0 +@1: bit $DD00 ; Wait until CLOCK IN is high + bvc @1 + lda #0 ; Clear $DD00 to simply receive algorithm sta $DD00 jsr receive_4_bytes lda #$FE @@ -398,15 +406,15 @@ L9B82: bvs L9B3D lda ST sbc $C3 sta $93 - bcs L9BAD + bcs @2 dex -L9BAD: plp - bcc L9BB1 +@2: plp + bcc @3 dex -L9BB1: stx $94 +@3: stx $94 ror $C3 ldx $C2 - beq L9BC8 + beq @4 dex stx $A5 txa @@ -416,166 +424,224 @@ L9BB1: stx $94 lda $94 adc #0 sta $AF -L9BC8: ldy #0 +@4: ldy #0 lda $C3 - bne L9BD7 - jsr receive_4_bytes + bne @8 + jsr receive_4_bytes ; in $C1..$C4 ldy #2 ldx #2 - bne L9BE5 -L9BD7: lda $C1 + bne @5 +@8: lda $C1 sta ($93),y iny -L9BDC: tya +@9: tya pha - jsr receive_4_bytes + jsr receive_4_bytes ; in $C1..C4 pla tay ldx #3 -L9BE5: cpy $A5 - bcs L9BED - lda $C1,x - sta ($93),y -L9BED: iny +@5: cpy $A5 + bcs @6 + lda $C1,x ; copy bytes ... + sta ($93),y ; ...to target memory +@6: iny cpy #$FE - bcs L9BF7 + bcs @7 dex - bpl L9BE5 - bmi L9BDC -L9BF7: jmp L9B3D + bpl @5 + bmi @9 +@7: jmp @back ; ---------------------------------------------------------------- .segment "drive_code_load" ; $0400 +sector_not_needed = $FF + drive_code_load: - lda $43 + lda $43 ; Number of sectors on current track sta $C1 -L9BFE: jsr L0582 -L9C01: bvc L9C01 +L9BFE: + ; + ; Here we wait for a sector header and read it + ; + jsr wait_for_header ; (sets Y=0) + ; 7 more bytes to read +@1: bvc @1 ; Loop until byte ready clv - lda $1C01 - sta $25,y + lda $1C01 ; Read next byte of header + sta $25,y ; Store iny - cpy #7 - bne L9C01 - jsr $F556 -L9C12: bvc L9C12 + cpy #7 ; Did we read 7 bytes? + bne @1 ; No? Read next byte + ; Sector header has been read + + ; + ; Now we read 5 bytes of the sector data + ; + jsr $F556 ; Wait for SYNC (sets Y=0) +@2: bvc @2 ; Loop until byte ready clv lda $1C01 sta ($30),y iny - cpy #5 - bne L9C12 - jsr $F497 + cpy #5 ; Did we read 5 bytes? + bne @2 ; No? Read next byte + jsr $F497 ; GCR decode header (not sector data) and write to $16..$1A + + ; Check checksum $1A = $16 xor $17 xor $18 xor $19 + ; Therefore xorring $16..$1A should result in 0 ldx #5 lda #0 -L9C26: eor $15,x +@3: eor $15,x dex - bne L9C26 + bne @3 tay - beq L9C31 -L9C2E: jmp $F40B - -L9C31: inx -L9C32: lda $12,x - cmp $16,x - bne L9C2E + beq @4 +@error: jmp $F40B ; Read error + + ; X=0 +@4: inx ; X=1 +@6: lda $12,x ; Compare expected header ID + cmp $16,x ; .. with read header ID + bne @error dex - bpl L9C32 - jsr $F7E8 - ldx $19 - cpx $43 - bcs L9C2E - lda $53 - sta L060F,x - lda $54 - sta L05FA,x - lda #$FF - sta L0624,x + bpl @6 + + jsr $F7E8 ; GCR decode first 5 bytes of sector data and write to $52..$55 + ldx $19 ; Is the sector number that we read smaller + cpx $43 ; than the number of sectors on this track? + bcs @error + lda $53 ; Store next track + sta track_links,x + lda $54 ; Store next sector + sta sector_links,x + lda #sector_not_needed + sta sector_order,x ; initialize array dec $C1 bne L9BFE + + ; + ; Now build the sector_order array + ; lda #1 sta $C3 - ldx $09 -L9C5D: lda $C2 - sta L0624,x + ldx $09 ; Sector last read +@7: lda $C2 ; Counter, initalized to 0 by drivecode_load_initialize + sta sector_order,x inc $C2 - lda L060F,x - cmp $08 - bne L9C75 - lda L05FA,x - tax + lda track_links,x + cmp $08 ; Next sector on the same track as last? + bne @8 ; Then sector_order array is finished + lda sector_links,x ; Chain to + tax ; next sector of file inc $C3 - bne L9C5D - beq L9C2E -L9C75: cmp #$24 - bcs L9C2E + bne @7 + beq @error ; If $C3 hits 0 (255 iterations), then there must be a cycle in the sector chain + + ; + ; When we arrive here we either need to continue on a different track, or + ; we hit the final sector of the file (A=0). Either way the sector_order array + ; is complete. + ; +@8: cmp #$24 ; Track >=36 ? + bcs @error ; Then a problem. NOTE: This is incompatible with dual sided disks on 1571. sta $08 - lda L05FA,x + lda sector_links,x sta $09 -L9C80: jsr L0582 + + ; + ; Wait for a sector header and read it + ; +@9: jsr wait_for_header ; (sets Y=0) iny -L9C84: bvc L9C84 + ; 3 more bytes to read +@10: bvc @10 ; Loop until byte ready clv lda $1C01 sta ($30),y iny cpy #4 - bne L9C84 + bne @10 ldy #0 - jsr $F7E8 - ldx $54 - cpx $43 - bcs L9C2E - lda L0624,x - cmp #$FF - beq L9C80 + jsr $F7E8 ; GCR decode the bytes + ldx $54 ; If sector number + cpx $43 ; >= number of sectors on track + bcs @error ; then there is a problem + lda sector_order,x + cmp #sector_not_needed ; If we don't need to read this sector, + beq @9 ; Wait for the next one stx $C0 - jsr $F556 -L9CA8: bvc L9CA8 + + ; + ; This is a sector we need. so read its contents + ; + jsr $F556 ; Wait for SYNC (sets Y=0) + ; Read 256 bytes in the buffer +@11: bvc @11 ; Loop until byte ready clv lda $1C01 sta ($30),y iny - bne L9CA8 + bne @11 + ; Read another 70 bytes in the auxiliary buffer at end of the stack ldy #$BA -L9CB5: bvc L9CB5 +@12: bvc @12 ; Loop until byte ready clv lda $1C01 sta $0100,y iny - bne L9CB5 + bne @12 + ; GCR decode bytes jsr $F7E8 - lda $53 - beq L9CCC - lda #0 + lda $53 ; Get link to next track ??? + beq @13 ; 0? Then skip + lda #0 ; Clear link to next sector ??? sta $54 -L9CCC: sta $34 +@13: sta $34 sta $C1 ldx $C0 - lda $0624,x + lda sector_order,x sta $53 - lda #$FF - sta L0624,x + lda #sector_not_needed ; We won't need this sector anymore + sta sector_order,x jsr $F6D0 lda #$42 sta $36 - ldy #$08 + + ; Signal C64 that we want to transmit + ldy #$08 ; Clock out high, data out low sty $1800 -L9CE8: lda $1800 + ; C64 will set DATA IN high if it is ready to receive +@14: lda $1800 lsr a - bcc L9CE8 + bcc @14 ldy #0 -L04F6: +@next: dec $36 sty $1800 - bne L9CFE - dec $C3 - bne L9C80 - jmp $F418 - -L9CFE: ldy $C1 + bne @transmit_buffer + dec $C3 ; Did we read all blocks? + bne @9 + jmp $F418 ; Set buffer status at $0001 to 01 (succesfull completion) + +@transmit_buffer: + ; 5 bytes of GCR data become 4 bytes of decoded data. But the GCR data will not be decoded + ; into raw data, but directly decoded into values that can be written to VIA register $1800. + ; In order to convert to register values, we will convert the 5 bytes GCR into 8 "quintets" + ; of 5 bits that we will store at $55..$5D. + ; + ; A "quintet" can be convert to 4 bits of decoded data by a lookup table, but we are not + ; going to generate decoded data, but VIA register values. We transmit two bytes at a time + ; over the serial bus via the clock and data lines. Thus in order to transmit 4 bits, we need + ; two VIA register values that will be transmited after each other. + ; + ; In other words, we need two 32 byte lookup tables. However, because in a GCR code, no two + ; zeros can occur in a row, the first 8 values will never occur and we can limit ourselves + ; to 24 byte lookup tables. + ; + ; Convert to nibbles: + ldy $C1 lda ($30),y lsr a lsr a @@ -585,11 +651,11 @@ L9CFE: ldy $C1 and #$07 sta $5D iny - bne L9D15 - iny + bne @16 ; Not end of regular buffer? + iny ; End of register buffer sty $31 - ldy #$BA -L9D15: lda ($30),y + ldy #$BA ; Continue from auxiliary buffer at $01BA +@16: lda ($30),y asl a rol $5D asl a @@ -638,76 +704,89 @@ L9D15: lda ($30),y lda ($30),y and #$1F sta $57 -L0564: iny sty $C1 - ldy #$08 +@transmit_tuple: + ; Transmit the 4-byte tuple to the C64 + ; $55..5D contain indexes into the tables with CIA register values + ldy #$08 ; Signal C64 with CLOCK OUT high, DATA OUT low sty $1800 ldx $55,y -: lda L05CA - 8,x ; ??? + ; Transmit bits 0-1 of the 4 bits of decoded data +@17: lda regvalue_lookup_01 - 8,x ; - 8 because the table is only 24 rather than 32 bytes sta $1800 - lda L05DA,x + ; Transmit bits 2-3 of the 4 bits of decoded data + lda regvalue_lookup_23 - 8,x ; - 8 because the table is only 24 rather than 32 bytes ldx $54,y sta $1800 dey - bne :- - jmp L04F6 + bne @17 +.assert >* = >@transmit_tuple, error, "Page boundary!" + jmp @next -L0582: +wait_for_header: ldx #3 stx $31 -L9D80: inx - bne L9D86 - jmp $F40B +@try_again: + inx + bne @try + jmp $F40B ; Read error -L9D86: jsr $F556 -L9D89: bvc L9D89 +@try: jsr $F556 ; Wait for SYNC on disk (sets Y=0) +@1: bvc @1 ; Loop until byte ready clv lda $1C01 - cmp $24 - bne L9D80 + cmp $24 ; Header block ID as expected? + bne @try_again rts -L059A: - ldx #$00 +drivecode_load_initialize: + ldx #$00 ; CLOCK OUT low, DATA OUT low stx $1800 stx $C2 - lda $19 - sta $09 - lda $18 - sta $08 -L9DA3: lda #$E0 + lda $19 ; Sector number last read sector (first sector of program file) + sta $09 ; Buffer 1 sector + lda $18 ; Track of last read reactor (first sector of program file) + sta $08 ; Buffer 1 track + ; The drive code is in memory at $400, the address of buffer 1. + ; So we want to send an execute command for buffer 1. +@2: lda #$E0 ; $E0 = read sector header and then execute code in buffer sta $01 -L9DA7: lda $01 - bmi L9DA7 - cmp #2 - bcs L9DBB +@1: lda $01 ; Wait until command has completed + bmi @1 + ; + ; If the command has completed, it means the load has completed. + ; + cmp #2 ; >=2 means error + bcs @error lda $08 - bne L9DA3 - lda #$02 + bne @2 + lda #$02 ; DATA OUT high, CLOCK OUT low sta $1800 - jmp $C194 + jmp $C194 ; Prepare status message -L9DBB: inx - ldy #$0A +@error: inx + ldy #$0A ; DATA out high, lock out high sty $1800 - jmp $E60A + jmp $E60A ; 21, 'read error' -L05CA: +regvalue_lookup_01: .byte 0, 10, 10, 2 .byte 0, 10, 10, 2 .byte 0, 0, 8, 0 .byte 0, 0, 8, 0 -L05DA: .byte 0, 2, 8, 0 .byte 0, 2, 8, 0 - .byte 0, 8, 10, 10, 0, 0, 2, 2 - .byte 0, 0, 10, 10, 0, 0, 2, 2 +regvalue_lookup_23: + .byte 0, 8, 10, 10 + .byte 0, 0, 2, 2 + .byte 0, 0, 10, 10 + .byte 0, 0, 2, 2 .byte 0, 8, 8, 8 .byte 0, 0, 0, 0 -L05FA: -L060F := L05FA + 21 -L0624 := L060F + 21 +sector_links: +track_links := sector_links + 21 +sector_order := track_links + 21 ; ---------------------------------------------------------------- ; drive code $0500 @@ -752,7 +831,7 @@ LA534: ldy #0 lda $81 sta ($94),y iny -LA542: jsr L0564 +LA542: jsr receive_byte sta ($30),y iny cpy L0611 @@ -1035,26 +1114,35 @@ LA734: jsr _load_FNADR_indy bne LA734 jmp $F654 ; UNLISTEN -LA742: jsr $F82E ; cassette sense - beq LA764 - ldy #$1B -LA749: jsr LA7B3 -LA74C: bit $DC01 - bpl LA766 + +tape_wait_play: + ; if already pressed, no need to display messages + jsr $F82E ; cassette sense + beq rts_carry_clear + ldy #$1B ; print PRESS PLAY ON TAPE +LA749: jsr LA7B3 ; print + ; Wait for key on tape, but allow run/stop to abort. + ; Run/stop is column 7, row 7 + ; $DC00 = $7f, = row 7 selected. Therefore test bit 7 of $DC01: +: bit $DC01 + bpl rts_carry_set + jsr $F82E ; cassette sense + bne :- + ldy #$6A ; Offset to OK + jmp LA7B3 ; print OK + +tape_wait_record: jsr $F82E ; cassette sense - bne LA74C - ldy #$6A - jmp LA7B3 - -LA75B: jsr $F82E ; cassette sense - beq LA764 - ldy #$2E -LA762: ; ??? + beq rts_carry_clear + ldy #$2E ; print PRESS RECORD & PLAY ON TAPE bne LA749 -LA764: clc + +rts_carry_clear: + clc rts -LA766: sec +rts_carry_set: + sec rts print_found: @@ -1118,7 +1206,7 @@ LA7C4: clc .segment "tape" -; ??? unused? +new_save_tape: ldx #load_ac_indy_end - load_ac_indy - 1 : lda load_ac_indy,x sta L0110,x @@ -1127,10 +1215,10 @@ LA7C4: clc ldx #5 stx $AB jsr $FB8E ; copy I/O start address to buffer address - jsr LA75B + jsr tape_wait_record bcc :+ lda #0 - jmp _disable_rom + jmp _disable_fc3rom : jsr LA77E jsr turn_screen_off jsr LA999 @@ -1183,17 +1271,18 @@ LA841: lda $D7 dey bne LA841 jsr LA912 - jmp _disable_rom + jmp _disable_fc3rom -LA851: jsr LA8C9 +tape_load_code: + jsr LA8C9 lda $AB cmp #2 - beq LA862 + beq :+ cmp #1 - bne LA851 + bne tape_load_code lda SA beq LA86C ; "LOAD"[...]",n,0" -> skip load address -LA862: lda $033C +: lda $033C sta $C3 lda $033D sta $C4 @@ -1210,7 +1299,7 @@ LA86C: jsr print_found LA880: dey jsr _load_FNADR_indy cmp $0341,y - bne LA851 + bne tape_load_code tya bne LA880 LA88C: sty ST @@ -1242,14 +1331,14 @@ LA88C: sty ST sta ST LA8C2: ldx $AE ldy $AF - jmp _disable_rom + jmp _disable_fc3rom LA8C9: jsr LA92B lda $BD cmp #0 ; XXX not needed beq LA8C9 sta $AB -LA8D4: jsr LA96E +LA8D4: jsr tape_read_byte lda $BD sta ($B2),y iny @@ -1259,7 +1348,7 @@ LA8D4: jsr LA96E LA8E2: jmp L0110 LA8E5: jsr LA92B -LA8E8: jsr LA96E +LA8E8: jsr tape_read_byte cpy $93 bne LA8E2 lda #$0B @@ -1279,7 +1368,7 @@ LA905: lda $C3 lda $C4 sbc $AF bcc LA8E8 - jsr LA96E + jsr tape_read_byte LA912: iny LA913: sty $C0 lda #0 @@ -1294,14 +1383,14 @@ LA913: sty $C0 clc rts -LA92B: jsr LA742 +LA92B: jsr tape_wait_play bcc LA939 pla pla pla pla lda #0 - jmp _disable_rom + jmp _disable_fc3rom LA939: jsr turn_screen_off sty $D7 @@ -1316,7 +1405,7 @@ LA945: jsr LA97E cmp #$F2 bne LA945 LA954: ldy #9 -LA956: jsr LA96E +LA956: jsr tape_read_byte lda $BD cmp #2 beq LA956 @@ -1324,19 +1413,20 @@ LA956: jsr LA96E beq LA956 LA963: cpy $BD bne LA945 - jsr LA96E + jsr tape_read_byte dey bne LA963 rts -LA96E: lda #8 +tape_read_byte: + lda #8 sta $A3 -LA972: jsr LA97E +: jsr LA97E rol $BD nop nop dec $A3 - bne LA972 + bne :- rts LA97E: lda #$10 diff --git a/core/vectors.s b/bank0/vectors.s similarity index 64% rename from core/vectors.s rename to bank0/vectors.s index 3004af6..fed436d 100644 --- a/core/vectors.s +++ b/bank0/vectors.s @@ -4,14 +4,14 @@ ; This is put right after the cartridge's "cbm80" header and ; contains jump table, which is mostly used from other banks. -.include "kernal.i" +.include "../core/kernal.i" .include "persistent.i" ; from init .import entry .import go_basic .import init_load_and_basic_vectors -.import init_vectors_jmp_bank_2 +.import init_vectors_goto_psettings ; from format .import fast_format @@ -30,19 +30,19 @@ .global jentry jentry: - jmp entry + jmp entry ; $804C ; this vector is called from other banks - jmp perform_operation_for_desktop + jmp perform_operation_for_desktop ; $995E .global jfast_format jfast_format: ; monitor calls this - jmp fast_format + jmp fast_format ;$96E4 ; these vectors are called from other banks - jmp init_read_disk_name - jmp init_write_bam - jmp init_vectors_jmp_bank_2 - jmp go_basic - jmp print_screen - jmp init_load_and_basic_vectors + jmp init_read_disk_name ;$96FB + jmp init_write_bam ; $971A + jmp init_vectors_goto_psettings ; $803B + jmp go_basic ; $80CE + jmp print_screen ; $9473 + jmp init_load_and_basic_vectors ; $A004 diff --git a/core/wrappers.s b/bank0/wrappers.s similarity index 94% rename from core/wrappers.s rename to bank0/wrappers.s index eb191bf..a77e179 100644 --- a/core/wrappers.s +++ b/bank0/wrappers.s @@ -4,7 +4,7 @@ ; This has no imports, and the only consumer is the BASIC ; extension. -.include "kernal.i" +.include "../core/kernal.i" .include "persistent.i" @@ -16,7 +16,7 @@ WAF08: lda #>($AF08 - 1) lda #<($AF08 - 1) ; SYNTAX ERROR disable_rom_jmp: pha - jmp _disable_rom + jmp _disable_fc3rom .global disable_rom_jmp_overflow_error disable_rom_jmp_overflow_error: @@ -76,9 +76,9 @@ WA663_E386: WE16F: ldx #>($E16F - 1) ldy #<($E16F - 1) ; LOAD jsr_with_rom_disabled: - lda #>(_enable_rom - 1) + lda #>(_enable_fcbank0 - 1) pha - lda #<(_enable_rom - 1) + lda #<(_enable_fcbank0 - 1) L98A3: pha txa ; push X/Y address pha @@ -116,4 +116,4 @@ WE175: lda #>($E175 - 1) lda #<($E175 - 1) ; LOAD worker pha lda #0 - jmp _disable_rom + jmp _disable_fc3rom diff --git a/bank3/bank3.cfg b/bank3/bank3.cfg new file mode 100644 index 0000000..6dda7dc --- /dev/null +++ b/bank3/bank3.cfg @@ -0,0 +1,87 @@ +MEMORY { + ROML: file = %O, start = $8000, size = $1E00, fill = yes, fillval = $ff; + ROMIO1L: start = $9E00, size = $0080, fill = yes, fillval = $ff, file = %O; + ROMIO1H: start = $9E00, size = $0080, fill = yes, fillval = $ff, file = %O; + ROMIO2L: start = $9F00, size = $00E0, fill = yes, fillval = $ff, file = %O; + ROMIO2H: start = $9F00, size = $0020, fill = yes, fillval = $ff, file = %O; + ROMHA: file = %O, start = $A000, size = $1000, fill = yes, fillval = $ff; + ROMHB: file = %O, start = $B000, size = $0FA0, fill = yes, fillval = $ff; + ROMHTOP: file = %O, start = $FFA0, size = $005A, fill = yes, fillval = $ff; + VECTORS: file = %O, start = $FFF8, size = $0006, fill = yes, fillval = $ff; + ULTIMAXF0: start = $F000, size = $0800; + ULTIMAXF8: start = $F800, size = $0100; + ULTIMAXF9: start = $F900, size = $0340; + ULTIMAXFF: start = $FFA0, size = $005A; + + FREEZERZP: start = $0070, size = $67, define=yes; + ZP98: start = $0098, size = $3F; + ZPA6_1: start = $00A6, size = $0E; + ZPA6_2: start = $00A6, size = $0E; + ZP40: start = $0040, size = $19; + ZP60: start = $0060, size = $09; + LOW0202: start = $0202, size = $2B; + RAM5000: start = $5000, size = $1000; + + IO1L: start = $DE00, size = $80; + IO1H: start = $DE80, size = $80; + IO2L: start = $DF00, size = $E0; + IO2H: start = $DFE0, size = $20; +} + +SEGMENTS { + freezer_zeropage: load=FREEZERZP, type=bss, define=yes; + freezer_entry_1: load=ROML, run=ROML, type=ro, define=yes; + backup_disk: load=ROML, run=ROML, type=ro, define=yes; + freezer_restore_0: load=ROML, type=ro, define=yes; + freezer_restore_1: load=ROML, type=ro, define=yes; + freezer_restore_2: load=ROML, type=ro, define=yes; + freezer_entry_2: load=ROML, run=ROML, type=ro, define=yes; + backup_disk_2: load=ROML, run=ROML, type=ro, define=yes; + freezer_entry_3: load=ROML, run=ROML, type=ro, define=yes; + backup_compress: load=ROML, run=ROML, type=ro, define=yes; + zp_load_mem_1: load=ROML, run=ZPA6_1, type=rw, define=yes; + zp_load_mem_2: load=ROML, run=ZPA6_2, type=rw, define=yes; + disk_backup_loader: load=ROML, type=ro, define=yes; + freezer_backup_tape: load=ROML, run=ROML, type=ro, define=yes; + tape_backup_loader: load=ROML, type=ro, define=yes; + freezer_monitor: load=ROML, run=ROML, type=ro, define=yes; + freezer_game_swap: load=ROML, run=ROML, type=ro, define=yes; + memswap: load=ROML, run=ZP98, type=rw, define=yes; + freezer_game: load=ROML, run=ROML, type=ro, define=yes; + freezer_reset: load=ROML, run=ROML, type=ro, define=yes; + mysterycode: load=ROML, run=ROML, type=ro, define=yes; + desktop_helper_2: load=ROML, run=ROML, type=ro, define=yes; + diredit_cmds: load=ROML, run=LOW0202, type=ro, define=yes; + mysterybytes: load=ROML, run=ROML, type=ro, define=yes; + screenshotcode: load=ROML, run=RAM5000, type=ro, define=yes; + romio1l: load=ROMIO1L, run=IO1L, type=ro, define=yes; + romio1h: load=ROMIO1H, run=IO1H, type=ro, define=yes; + romio2l: load=ROMIO2L, run=IO2L, type=ro, define=yes; + romio2h: load=ROMIO2H, run=IO2H, type=ro, define=yes; + + printersettings: load=ROMHA, run=ROMHA, type=ro, define=yes; + ramload: load=ROMHA, run=ZP60, type=ro, define=yes; + copycode: load=ROMHA, run=ZP40, type=ro, define=yes; + junk0: load=ROMHA, run=ROMHA, type=ro, define=yes; + ramcode: load=ROMHA, run=ROMHA, type=ro, define=yes; + mysterybytes2: load=ROMHA, run=ROMHA, type=ro, define=yes; + ramcode2: load=ROMHA, run=ROMHA, type=ro, define=yes; + + freezer_graphics: load=ROMHB, run=ULTIMAXF0, type=ro, define=yes; + mysterybytes3: load=ROMHB, run=ULTIMAXF0, type=ro, define=yes; + view_graphics: load=ROMHB, run=ULTIMAXF8, type=ro, define=yes; + freezer_menu: load=ROMHB, run=ULTIMAXF9, type=ro, define=yes; + mysterybytes4: load=ROMHB, run=ULTIMAXF9, type=ro, define=yes; + freezer_menu_16k: load=ROMHB, run=ROMHB, type=ro, define=yes; + mysterybytes5: load=ROMHB, run=ROMHB, type=ro, define=yes; + freezer: load=ROMHTOP, run=ROMHTOP, type=ro, define=yes; + freezer_vectors: load=VECTORS, run=VECTORS, type=ro, define=yes; +} + +SYMBOLS { + pset: type=weak, value=$8023; + monitor: type=weak, value=$AB00; + freezer_exec_menu: type=weak, value=$F900; + show_view_menu: type=weak, value=$BC5B; + freezer_update_spritepointers: type=weak, value = $bc40; +} diff --git a/bank3/desktop_helper2.s b/bank3/desktop_helper2.s new file mode 100644 index 0000000..56bbb19 --- /dev/null +++ b/bank3/desktop_helper2.s @@ -0,0 +1,460 @@ +;***************************************************************************** +; Final Cartridge III reconstructed source code +; +; After the user has reordered the entries in a directory using the desktop, +; this code writes back the directory to disk in the desired order. +;***************************************************************************** + + .setcpu "6502x" + +.include "../core/kernal.i" +.include "../core/fc3ioreg.i" +.include "persistent.i" + +.import load_ae_rom_hidden +.import __diredit_cmds_LOAD__,__diredit_cmds_RUN__,__diredit_cmds_SIZE__ + +.segment "desktop_helper_2" + +.global W9200 +W9200: + jsr write_directory_back_to_disk + lda #fcio_nmi_line | fcio_bank_0 + jmp _jmp_bank + +.global fill_loop + +write_directory_back_to_disk: + ; Fill $A000..$BFFF with #$00 + lda #>$A000 + sta $AD + ldx #$20 ; Fill $2000 bytes + lda #$00 + tay + sta $AC +fill_loop: +: sta ($AC),y + iny + bne :- + inc $AD + dex + bne :- + + ; Copy directory editing commands to low RAM + ldx #<(__diredit_cmds_SIZE__-1) +: lda __diredit_cmds_LOAD__,x + sta $0202,x + dex + bpl :- + + jsr open_hash_on_chan_2 + lda #$00 + sta $AC + sta $AE + sta $C1 + lda #>$A000 + sta $AD +: jsr send_read_block + jsr send_seek_0 + jsr read_sector_from_chan_2 + inc $AD ; Increasepointer for next sector + cpx #$00 ; End of directory? + beq directory_read_complete + cpx #18 ; Not on track 18? + bne close ; Then blast off. + cmp #19 ; Sector >= 19? + bcs close ; Then blast off. + jsr nibble2ascii + ; Store sector number in command + stx read_block+10 + sta read_block+11 + lda $AD + cmp #$B0 ; Do not read beyond $B000 + bcc :- +close: + jsr close_chn2 + lda #$80 ; DEVICE NOT PRESENT ERROR + sta $90 ; Statusbyte ST of I/O KERNAL + rts + +directory_read_complete: + ; + ; The old directory is stored at $A000. Now build the new directory + ; at $B000. + ; + lda #>$B000 + sta $C2 + lda $0200 + sta $C3 + lda $0201 + sta $C4 + + ; Count the number of dir entries + ldy #$00 + sty $AE + sty $0200 + lda #>$A000 + sta $AF + ldy #$02 ; Get file type +@1: jsr _load_ae_rom_hidden + bpl :+ ; If slot not in use, skip. + inc $0200 ; Count a dir entry. +: jsr next_dir_entry + bcc @1 ; Last dir entry? + +next_file: + ; We search the entire directory for every file name, so start at $A000 + lda #>$A000 + sta $AF + ldy #<$A000 + sty $AE + ; Y=0 + lda ($C3),y + tax + bne :+ ; All files processed? + jmp write_dir_to_disk ; Then write dir to disk. +: jsr inc_c3c4_beyond_z + txa + bmi insert_line ; Do we need to insert a line? + dec $0200 +process_dir_entry: + ldy #$02 ; Get file type + jsr _load_ae_rom_hidden + bpl entry_not_found + ; Adjust pointer to file name + lda #$05 + ora $AE + sta $AE + ; Compare file name + ldy #$00 +: lda ($C3),y + beq :+ + jsr _load_ae_rom_hidden + cmp ($C3),y + bne entry_not_found ; File name not equal + iny + cpy #$11 ; If desktop passes too long file name (should not occur) + bne :- + beq no_space_left +: cpy #$10 + beq :+ + jsr _load_ae_rom_hidden + cmp #$A0 ; First character beyond file name must be white space ($A0) + bne entry_not_found +: ; We found the file name in the directory + iny + tya + jsr add_to_c3c4 + ldy #$00 + lda $AE + and #$F0 ; Reset pointer to start of file entry + sta $AE + ; Copy the entry to destination + lda #$00 + sta ($C1),y + iny + sta ($C1),y + iny +: jsr _load_ae_rom_hidden + sta ($C1),y + iny + cpy #$20 + bne :- +inc_dest_ptr: + ; Increase destination pointer + tya + clc + adc $C1 + sta $C1 + bcc next_file + inc $C2 + lda $C2 + cmp #>$C000 ; Destination buffer full? + bcc next_file +no_space_left: +@c: jmp close + +entry_not_found: + jsr next_dir_entry + bcs no_space_left + jmp process_dir_entry + +.global next_dir_entry +next_dir_entry: + lda $AE + and #$F0 + clc + adc #$20 + sta $AE + bcc :+ + inc $AF +: lda $AF + cmp $AD + rts + +insert_line: + ldy #$FF + jsr inc_c3c4_beyond_z + ldy #$00 +: lda dirline,y + sta ($C1),y + iny + cpy #$20 + bne :- + beq inc_dest_ptr ; Always + +write_dir_to_disk: + lda $0200 + bne no_space_left + ; Start at sector 1 + lda #'0' + sta write_block+10 + lda #'1' + sta write_block+11 + lda $C1 + bne :+ + dec $C2 ; Prevent writing an empty sector +: lda #<$B000 + sta $AE + lda #>$B000 + sta $AF + lda #$02 + sta $AC +next_sector: + ldy #$00 + lda $AF + cmp $C2 + bcs :+ + lda #18 + sta ($AE),y + iny + lda $AC + sta ($AE),y + bne not_last_sector +: tya + ; Last sector, Y=0 +.global store_a_ff_to_ae +store_a_ff_to_ae: + sta ($AE),y + lda #$FF + iny + sta ($AE),y +.global not_last_sector +not_last_sector: + lda $AC + sec + sbc #$01 + jsr nibble2ascii + ; Store sector number + stx write_block+10 + sta write_block+11 + jsr send_seek_0 + jsr send_256byte_to_channel_2 + jsr send_write_block + lda $AF + cmp $C2 + bcs :+ + inc $AF + inc $AC + jmp next_sector + + ; Now do the BAM. + ; This is a simplistic algorithm: All sectors in track 18 are initially + ; assumed used. We have the number of sectors used in $AC, so a 0 is + ; shifted in $AC times. +: lda #19 ; Track 18 has 19 sectors + sec + sbc $AC + sta $C1 + lda #$FF + sta $C2 + sta $C3 + sta $C4 +: clc + rol $C2 + rol $C3 + rol $C4 + dec $AC + bne :- + lda $C4 + and #$07 + sta $C4 + ; Update the BAM. Update commands for sector 0 + lda #'0' + sta read_block+10 + sta read_block+11 + sta write_block+10 + sta write_block+11 + jsr send_read_block + jsr send_seek_72 ; BAM for track 18 at offset 72 + lda #$62 + jsr listen_second + ldx #$00 +: lda $C1,x + jsr IECOUT + inx + cpx #4 + bne :- + jsr UNLSTN + jsr send_write_block + + ; Send an "I" to command channel to make the drive reread the directory. + lda #$6F + jsr listen_second + lda #'I' + jsr IECOUT + jsr UNLSTN + jmp close_chn2 + +send_256byte_to_channel_2: + lda #$62 + jsr listen_second + ldy #$00 +: jsr _load_ae_rom_hidden + jsr IECOUT + iny + bne :- + jmp UNLSTN + +; +; Reads a sector from channel 2. +; +; The 254 bytes payload of a sector are stored in ($AC)+2 onwards. +; Pointer $AC/$AD is not increased +; +; Returns: +; +; A - Link to next sector +; X - Link to next track +; +read_sector_from_chan_2: + lda #$62 + jsr talk_second + ldy #$02 + jsr IECIN + tax + jsr IECIN + pha +: jsr IECIN + sta ($AC),y + iny + bne :- + jsr UNTALK + pla + rts + +open_hash_on_chan_2: + lda #$00 + sta $90 + lda #$F2 + jsr listen_second + lda $90 + bmi except_exit + lda #'#' + jsr IECOUT + jmp UNLSTN + +close_chn2: + lda #$E2 + jsr listen_second + jmp UNLSTN + +listen_second: + pha + lda $BA ; Current device number + jsr LISTEN + pla + jmp SECOND + +talk_second: + pha + lda $BA ; Current device number + jsr TALK + pla + jmp TKSA + +send_read_block: + ldx #<(read_block - __diredit_cmds_RUN__) + .byte $2c +send_write_block: + ldx #<(write_block - __diredit_cmds_RUN__) + .byte $2c +send_seek_0: + ldx #<(seek_0 - __diredit_cmds_RUN__) + .byte $2c +send_seek_72: + ldx #<(seek_72 - __diredit_cmds_RUN__) + lda #$6F ; Listen channel 15 + jsr listen_second +: lda __diredit_cmds_RUN__,x + beq :+ + jsr IECOUT + inx + bne :- +: jsr UNLSTN + ; Check for error omn cmd channel 15 + lda #$6F + jsr talk_second + jsr IECIN + pha +: cmp #$0D + beq :+ + jsr IECIN + bne :- +: jsr UNTALK + pla + cmp #$30 + beq _rts2 +except_exit: + ; Error condition. Pull return address and abort directory write back. + pla + pla + jmp close + +inc_c3c4_beyond_z: + ; Search for a 0 byte +: iny + lda ($C3),y + bne :- + iny + tya +add_to_c3c4: + ; Add the number of bytes to $C3/$C4 + clc + adc $C3 + sta $C3 + bcc _rts2 + inc $C4 +_rts2: rts + +; +; Convert a nibble (actually a number 0..19) to ASCII with fixed with. +; +; IN: A - Nibble +; +; OUT: A - Least significant digit +; X - Most sigificant digit +; +.proc nibble2ascii + ldx #'0' + cmp #$0A + bcc :+ + inx + sbc #$0A +: ora #'0' + rts +.endproc + +dirline: + .byte $00, $00, $80, $12, $00, '-', '-', '-' + .byte '-', '-', '-', '-', '-', '-', '-', '-' + .byte '-', '-', '-', '-', '-', $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + +.segment "diredit_cmds" + +read_block: .asciiz "U1:2 0 18 01" ; Read block on channel 2 from drive 0, track 18 sector 1 +write_block: .asciiz "U2:2 0 18 01" ; Write block on channel 2 to drive 0, track 18 sector 1 +seek_0: .asciiz "B-P 2 0" ; Seek channel 2 to position 0 +seek_72: .asciiz "B-P 2 72" ; Seek channel 2 to position 72 + diff --git a/bank3/disk_backload/Makefile b/bank3/disk_backload/Makefile new file mode 100644 index 0000000..f1a55b9 --- /dev/null +++ b/bank3/disk_backload/Makefile @@ -0,0 +1,13 @@ +all: backup_loader.prg + +basic_stub.bin: basic_stub.bas + petcat -w2 -l 0x0801 -o $@ $< + +backup_loader.o: backup_loader.s basic_stub.bin + ca65 --target c64 -l backup_loader.lst -o $@ $< + +backup_loader.prg: backup_loader.o + cl65 -m backup_loader.map -C backup_loader.cfg -o $@ $< + +clean: + rm -f *.o *.bin *.prg *.hexdump *.map *.lst diff --git a/bank3/disk_backload/backup_loader.cfg b/bank3/disk_backload/backup_loader.cfg new file mode 100644 index 0000000..85e9ca3 --- /dev/null +++ b/bank3/disk_backload/backup_loader.cfg @@ -0,0 +1,30 @@ +MEMORY { + BASICSTUB: + file = %O, + fill = yes, + fillval = $ff, + start = %S - $0801, + size = 14; + MAIN: + file = %O, + start = $080D, + size = $2000, + define = yes; + LOW: + file="", + fill=no, + start=$0200, + size=$0200; + DRIVE: + file="", + fill=no, + start=$0400, + size=$0200; +} + +SEGMENTS { + BASIC_STUB: load = BASICSTUB, type = ro; + CODE: load=MAIN, type=ro; + DRIVECODE: load=MAIN, run=DRIVE, type=rw, define=yes; + LOWCODE: load=MAIN, run=LOW, type=rw, define=yes; +} diff --git a/bank3/disk_backload/backup_loader.s b/bank3/disk_backload/backup_loader.s new file mode 100644 index 0000000..f3317f2 --- /dev/null +++ b/bank3/disk_backload/backup_loader.s @@ -0,0 +1,724 @@ +.import __LOWCODE_LOAD__, __LOWCODE_RUN__ +.import __DRIVECODE_LOAD__ +.import __MAIN_LAST__ + +.include "../../core/kernal.i" + +; +; This is the loader that loads and continues a Final Cartridge III disk +; backup. It is stored in the "FC" file along with the contents of memory +; til $0402. Most data is stored in a file "-FC" that stores the +; memory contents from $0403 to $fffd. This file is RLE compressed and +; needs decompression. +;. +; Zeropage, stack, $0200..0402 and colour RAM is included in the loader +; and starts right after code end. +; + +.segment "BASIC_STUB" + +.incbin "basic_stub.bin" + +.segment "CODE" + +stored_zeropage = __MAIN_LAST__ + $0000 +stored_stack = __MAIN_LAST__ + $0100 +stored_colram = __MAIN_LAST__ + $0200 +stored_vicregs = __MAIN_LAST__ + $0400 +stored_0400 = __MAIN_LAST__ + $042f + +nr_vicregs = $2f + +start: + sei + ; Backup the file name of the loader + ldy #$00 +: lda ($BB),y ; Pointer: current file name + sta filename_load+1,y + iny + cpy #15 + beq :+ + cpy $B7 ; Length of current file name + bne :- +: lda #$00 ; Terminate with a zero + sta filename_load+1,y + + ; NTSC C64s have a higher clock speed, so an extra nop needs to be + ; inserted in the receive code. + lda $02A6 ; Indicator PAL/NTSC, 0=NTSC, 1=PAL + bne @pal + ldx #ntsc_move_len-1 +: lda receive_4_bytes_load+ntsc_point_ofs,x + sta receive_4_bytes_load+ntsc_point_ofs+1,x + dex + bpl :- + + dec receive_4_bytes_load+ntsc_jump_ofs+2 ; Adjust branch to longer code length + +@pal: lda #$7F + sta $DC0D ; Interrupt control register CIA #1 + sta $DD0D ; Interrupt control register CIA #2 + + ; Initialize all SID voices + ldx #14 ; Start with voice 3, iterate down +: lda #$80 + sta $D402,x ; Pulse width low byte + sta $D403,x ; Pulse width high byte + lda #$21 ; Sawtooth + voice on + sta $D404,x ; Voice control register + lda #$08 + sta $D405,x ; Attack/Decay + lda #$80 + sta $D406,x ; Sustain/Release + txa + sec + sbc #$07 ; Subtract 7 for next voice + tax + bpl :- + + lda #$8F + sta $D418 ; Select volume and filter mode + ldx #$00 + stx $DC0E ; Control register A of CIA #1 + + ; + ; Note that the freezer, upon entry, searches for two memory areas: + ; one contains a backup of $0070..$00d6, the other the "restore" + ; routine. + ; + ; The loader restores the memory in this state, i.e. after loading + ; memory, $0070..$00d6 still can be used by the loader, and the restore + ; routine is loaded from backup as well. It can ultimately do an rts to + ; activate the restore routine that restores both memory areas and + ; returns control to the program. + + @1: ; Restore the zero page + lda stored_zeropage,x + sta $00,x + ; Restore the stack + lda stored_stack,x + sta $0100,x + + ; Restore the $0400..$0402 + cpx #$03 + bcs :+ + lda stored_0400,x + sta $0400,x +: inx + bne @1 + + ldx #nr_vicregs-1 +: lda stored_vicregs,x + sta $D000,x + dex + bpl :- + + lda #$0B ; Disable screen + sta $D011 ; $93 contains the backed up stack pointer + ldx $93 + txs + + ; Restore the colour ram + ; Colour ram is stored in a compacted form, as it is only 4-bit, two colour + ; RAM locations fit in a byte. + ldx #$00 +: lda stored_colram,x + jsr nibble2ay + sta $D800,x ; Color RAM + tya + sta $DA00,x ; Color RAM + lda stored_colram + $0100,x + jsr nibble2ay + sta $D900,x ; Color RAM + tya + sta $DB00,x ; Color RAM + + ; Install lowcode in page $0300 + lda __LOWCODE_LOAD__ + $0100,x + sta $0300,x + inx + bne :- + + ; Open the second (main) file of the backup + jsr open_second_file + + jsr UNTALK + + ; Upload the drive code and execute it + jsr upload_drivecode + lda #drivecode_entry + jsr IECOUT + jsr UNLSTN + + ; Install lowcode in page $0200 + sei +: lda __LOWCODE_LOAD__,y + sta $0200,y + iny + bne :- + + ; Y=0 + sty $96 + + ; Now pages $0200 and $0300 are coming. Skip for now. +: jsr receive_byte + jsr receive_byte + iny + bne :- + +: jsr receive_byte + sta vectors_tmp,y + iny + cpy #$03 + bne :- + + jsr receive_byte + sta $91 + sta cdsl+1 ; Self-modify code + jsr receive_byte + sta $92 + sta cdsh+1 ; Self modify code + lda #$35 + sta $01 ; 6510 I/O register + ldy #0 + jmp receive_main_memory + +.proc nibble2ay + pha + lsr + lsr + lsr + lsr + tay + pla + and #$0F + rts +.endproc + +.proc upload_drivecode + ldx #4 + lda #<__DRIVECODE_LOAD__ + sta $C3 ; Transient tape load + lda #>__DRIVECODE_LOAD__ + sta $C4 ; Transient tape load + ; Send M-W +@bl: lda #'w' + jsr send_Mx + tya + jsr IECOUT + txa + jsr IECOUT + lda #' ' + jsr IECOUT +: lda ($C3),y + jsr IECOUT + iny + tya + and #$1F + bne :- + jsr UNLSTN + tya + bne @bl + inc $C4 ; Transient tape load + inx + cpx #$06 + bcc @bl + ; Send M-E + lda #'e' +send_Mx: + pha + lda #$08 + jsr LISTEN + lda #$6F ; Command channel 15 + jsr SECOND + lda #'m' + jsr IECOUT + lda #'-' + jsr IECOUT + pla + jmp IECOUT +.endproc + +.segment "DRIVECODE" +jobqueue_entry: + jmp read_track ; This is executed by means of the $e0 command of the 1541 + ; job queue. + +drivecode_entry: + ldx #$00 + stx $1800 + lda $19 ; Transient strings stack + sta $09 ; Screen column after last TAB + lda $18 ; Last transient strings address + sta $08 ; Flag: search the quotation marks at the end of one string + ; This drive code is uploaded at $0400, buffer 1 in 1541 memory and also extends into buffer 2 + ; at $0500. $01 is the memory location of the 1541 job queue where to send commands for buffer + ; 1. By writing the $e0 command into the job queue, the 1541 preares for reading a sector + ; (moving the head etc.) and tnen executes the program in the buffer. + ; Code will start executing at jobqueue_entry + +@1: lda #$E0 + sta $01 +: lda $01 + bmi :- ; Wait until the $e0 command finishes. + cmp #$02 ; Error condition + bcs :+ ; then jump + lda $08 ; Last track?? + bne @1 ; No, then loop +: lda #$02 + sta $1800 + jmp $C194 ; Prepare status message + +read_track: + ; The fastloader won't just read a sector, it will read all sectors + ; in the current track that belong to the file and transmit them + ; to the C64 + +@2: ldx #>$0300 ; Buffer 0 at $0300 the buffer we will read into + stx $31 +@1: inx + bne :+ + jmp $F40B ; Read error + + ; Read a sector header +: jsr $F556 ; Wait for SYNC on disk (sets Y=0) +: bvc :- ; Wait for a byte ready + clv + lda $1C01 + cmp $24 ; Header block ID as expected? + bne @1 ; No, then loop to get next header + iny +: bvc :- ; Wait for a byte ready + ; Now read 4 bytes + clv + lda $1C01 + sta ($30),y ; Store into buffer + iny + cpy #$04 + bne :- + + ldy #$00 + jsr $F7E8 ; GCR decode first 5 bytes of sector data and write to $52..$55 + ldx $54 + cpx $09 ; Does the header sector number match the one we want to read? + bne @2 ; No then retry + + ; + ; After the header comes the sector itself + jsr $F556 ; Wait for SYNC on disk (sets Y=0) + ; Now read 256 bytes +: bvc :- + clv + lda $1C01 + sta ($30),y + iny + bne :- + + ldy #$BA ; Read another 70 bytes +: bvc :- + clv + lda $1C01 + sta $0100,y ; Use end of the stack as temporary storage area + iny + bne :- + + lda #$42 ; 66 GCR tuples to decode + + sta $36 ; GCR byte counter + ldy #0 + sty $C1 ; Offset in buffer +@3: dec $36 ; Pointer: strings for auxiliari programs + sty $1800 ; DATA OUT low, CLOCK OUT low + bne :+ ; More tuples to decode? + + lda $08 ; Flag: search the quotation marks at the end of one string + cmp $22 ; Utility programs pointers area + beq @2 + jmp $F418 ; buffer status at $0001 to 01 (succesfull completion) + + ; A GCR tuple consists of 8 groups of 5 bits to be decoded to 8 * 4 bit. + ; The following extracts all 8 groups and transmits them. The GCR decode happens during + ; transmission by table lookup. +: ldy $C1 + lda ($30),y ; First 5 bits + lsr + lsr + lsr + sta $5C + + lda ($30),y ; Second 5 bits spread over byte 0 and 1 + and #$07 + sta $5D ; Scratch for numeric operation + iny + bne :+ + iny + sty $31 ; Set $31 to 1 + ldy #$BA ; 70 bytes left to decode +: lda ($30),y ; Remaining bits in byte 1 + asl + rol $5D ; Shift into $5D + asl + rol $5D ; Shift into $5D + + lsr ; Third 5 bits in byte 1 + lsr + lsr + sta $5A + + lda ($30),y ; Fourth 5 bits spead over byte 1 and 2 + lsr + iny + lda ($30),y ; Byte 2 + rol + rol + rol + rol + rol + and #$1F + sta $5B + + lda ($30),y ; Fifth 5 bits spread over byte 2 and 3 + and #$0F + sta $58 + iny + lda ($30),y ; Byte 3 + asl + rol $58 ; Shift into $58 + lsr + lsr + lsr + sta $59 + + lda ($30),y ; Sixth 5 bits in byte 3 and 4 + asl + asl + asl + and #$18 + sta $56 + iny ; Byte 4 + lda ($30),y ; Pointer: BASIC starting arrays + rol + rol + rol + rol + and #$07 + ora $56 + sta $56 + + ; Indicate readyness for transmission and wait for C64 to ack + lda #$08 + sta $1800 +: lda $1800 + lsr + bcc :- + + lda #$00 + sta $1800 + + lda ($30),y ; Seventh 5 bits + and #$1F + sta $57 ; Scratch for numeric operation + iny + sty $C1 ; I/O starting address + lda $36 ; Pointer: strings for auxiliari programs + cmp #$41 ; Last tuple? + bne :+ ; No then skip + + ; GCR decode track/sector no. for next sector of file + ldx $5A + lda $F8A0,x ; ROM GCR table for high nibbles + ldx $5B + ora $F8C0,x ; ROM GCR table for low nibbles + sta $08 + ldx $58 + lda $F8A0,x ; ROM GCR table for high nibbles + ldx $59 + ora $F8C0,x ; ROM GCR table for low nibbles + sta $09 + +: ldy #$08 ; Start transmission + sty $1800 + ldx $55,y +: lda regvalue_lookup_01-8,x ; GCR table first two bits + sta $1800 + lda regvalue_lookup_23-8,x ; GCR table second two byts + ldx $54,y + sta $1800 + dey + bne :- + jmp @3 + +regvalue_lookup_01: + .byte 0, 10, 10, 2 + .byte 0, 10, 10, 2 + .byte 0, 0, 8, 0 + .byte 0, 0, 8, 0 + .byte 0, 2, 8, 0 + .byte 0, 2, 8, 0 +.assert >* = >(regvalue_lookup_01-8), error, "Page boundary!" + +regvalue_lookup_23: + .byte 0, 8, 10, 10 + .byte 0, 0, 2, 2 + .byte 0, 0, 10, 10 + .byte 0, 0, 2, 2 + .byte 0, 8, 8, 8 + .byte 0, 0, 0, 0 +.assert >* = >(regvalue_lookup_23-8), error, "Page boundary!" + + +.SEGMENT "LOWCODE" + + +.proc receive_byte + lda $96 + bne :+ + jsr receive_4_bytes + ldx #0 + lda #$FE + sta $96 +: txa + bpl :+ + jsr receive_4_bytes + ldx #3 +: lda $C1,x ; I/O starting address + dec $96 + dex + rts +.endproc + +.proc receive_4_bytes + ; X,Y preserved + + tya + pha +: bit $DD00 ; Wait clock + bvs :- + lda #$20 + sta $DD00 ; Data port A #2: serial bus, RS-232, VIC memory +: bit $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + bvc :- + lda #$00 + sta $DD00 ; Data port A #2: serial bus, RS-232, VIC memory +: bit $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + bvs :- + ldy #$03 + nop + lda $01 ; 6510 I/O register +ll: lda $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + lsr + lsr + nop +ntsc_point: + nop + ora $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + lsr + lsr + nop + nop + ora $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + lsr + lsr + nop + nop + ora $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + sta $00C1,y ; I/O starting address + dey +ntsc_jump: + bpl ll + pla + tay + rts +ntsc_end: + nop +.endproc + +receive_4_bytes_load = receive_4_bytes - __LOWCODE_RUN__ + __LOWCODE_LOAD__ +ntsc_point_ofs = receive_4_bytes::ntsc_point - receive_4_bytes +ntsc_jump_ofs = receive_4_bytes::ntsc_jump - receive_4_bytes +ntsc_move_len = receive_4_bytes::ntsc_end - receive_4_bytes::ntsc_point + +receive_main_memory: + ; Retrieve compressed memory via the fastloader +: jsr receive_byte + dec $01 ; I/O invisible + sta ($91),y + inc $01 ; I/O visible + inc $91 ; Increase pointer low byte + bne :- + inc $92 ; Increase pointer high byte + bne :- + +: lda $96 ; Receive but ignore sector slack + beq :+ + jsr receive_byte + jmp :- + + ; Compressed memory has been retrieved, now start decompression +: lda #$34 + sta $01 ; 6510 I/O register +cdsl: + lda #<$FFFF ; Self modified with start of compressed data (L) + sta $96 +cdsh: + lda #>$FFFF ; Self modified with start of compressed data (H) + sta $97 + lda #<$0403 ; Decompress from $0403 onwards + sta $91 + lda #>$0403 ; Decompress from $0403 onwards + sta $92 + ldx #0 +@5: + lda ($96),y + bne @7 + jsr load_next_byte + tax +@9: + jsr load_next_byte + jsr store_next_byte + dex +@6: + bne @9 +@2: + jsr load_next_byte + lda $91 + cmp #<$FFFD + lda $92 + sbc #>$FFFD ; Are we ready with decompression?? + bcc @5 ; No then loop. + bcs farcode ; Always + +@7: tax + dex + bne @8 + jsr load_next_byte + pha + jsr load_next_byte + sta $90 +: jsr load_next_byte + jsr store_next_byte + inx + bne :- + dec $90 + bne :- + pla + tax + sec + bcs @6 ; Always +@8: dex + beq @4 + inx + inx + jsr load_next_byte +@3: jsr store_next_byte + dex +@1: bne @3 + beq @2 ; Always +@4: jsr load_next_byte + pha + jsr load_next_byte + sta $90 + jsr load_next_byte +: jsr store_next_byte + inx + bne :- + dec $90 + bne :- + sta $90 + pla + tax + lda $90 + cpx #$00 + sec + bcs @1 ; Always + +.proc load_next_byte + inc $96 + bne :+ + inc $97 +: lda ($96),y + rts +.endproc + +.proc store_next_byte + sta ($91),y + inc $91 + bne :+ + inc $92 +: rts +.endproc + + +farcode: + lda #$36 + sta $01 ; 6510 I/O register + + ; Weird... this is the RS232 interrupt enable byte. No idea what is being done here: + ldy #$00 + sty $02A1 + + ; Put the vectors at the right place + ldx #$02 +: lda vectors_tmp,x + sta $FFFD,x + dex + bpl :- + + ; Close the second file + lda #$08 + jsr LISTEN + lda #$E0 + jsr SECOND + jsr UNLSTN + + ; Reopen the second file + jsr open_second_file + + ; Now retrieve page $0200 without fastloader +: jsr IECIN + sta $0200,y + iny + bne :- + + ; The freezer has written the freeze_restore_0300 routine into the zero page at $00a6 + ; before writing memory to disk. This routine loads the $0300 page from disk and + ; returns control to the program. + ; + ; we jump to there with rts + lda #$00 + pha + lda #$A5 + pha + rts + +.proc open_second_file + lda #$08 + jsr LISTEN + lda #$F0 ; $F0 = OPEN channel 0 + jsr SECOND + + ; send the file name + ldy #0 +: lda filename,y ; Tape I/O buffer + beq :+ + jsr IECOUT + iny + bne :- +: jsr UNLSTN + + ; Talk the file + lda #$08 + jsr TALK + ldy #$00 + lda #$60 + jmp TKSA +.endproc + +filename: + .byte "-1234567890123456" + +filename_load = filename - __LOWCODE_RUN__ + __LOWCODE_LOAD__ + +vectors_tmp = * diff --git a/bank3/disk_backload/basic_stub.bas b/bank3/disk_backload/basic_stub.bas new file mode 100644 index 0000000..e1912c7 --- /dev/null +++ b/bank3/disk_backload/basic_stub.bas @@ -0,0 +1 @@ +1986 sys2061 diff --git a/bank3/freezer_backup.s b/bank3/freezer_backup.s new file mode 100644 index 0000000..0ad3814 --- /dev/null +++ b/bank3/freezer_backup.s @@ -0,0 +1,811 @@ +;***************************************************************************** +; Final Cartridge III reconstructed source code +; +; This file implements the backup functionality of the freezer +;***************************************************************************** + + .setcpu "6502x" + +.include "../core/kernal.i" +.include "../core/fc3ioreg.i" +.include "persistent.i" + +.import __tape_backup_loader_LOAD__,__tape_backup_loader_SIZE__ +.import __disk_backup_loader_LOAD__,__disk_backup_loader_SIZE__ +.import __zp_load_mem_1_LOAD__,__zp_load_mem_1_SIZE__ +.import __zp_load_mem_2_LOAD__,__zp_load_mem_2_SIZE__ +.importzp __zp_load_mem_1_RUN__,__zp_load_mem_2_RUN__ +.importzp tmpvar1,tmpptr_a,spritexy_backup +.import write_mg87_and_reset + +.segment "backup_disk" + +.global freezer_backup_disk + +freezer_backup_disk: + lda #$00 + sta $D015 ; Disable sprites + sta $D418 ; Mute sound + ldy #$06 + jsr set_1541_sector_interleave + jsr open_fc + lda #<__disk_backup_loader_LOAD__ + sta tmpptr_a + lda #>__disk_backup_loader_LOAD__ + sta tmpptr_a+1 + + ldy #0 +@1: lda (tmpptr_a),y + jsr IECOUT + inc tmpptr_a + bne :+ + inc tmpptr_a+1 +: lda tmpptr_a + cmp #<(__disk_backup_loader_LOAD__ + __disk_backup_loader_SIZE__) + lda tmpptr_a+1 + sbc #>(__disk_backup_loader_LOAD__ + __disk_backup_loader_SIZE__) + bcc @1 + + ; Backup the zero page + ldx #$00 +@2: lda $00,x + cpx #spritexy_backup ; ???? No backup of sprite 2 x coord? + bne :+ + lda #$00 +: jsr IECOUT + inx + bne @2 + + ; Backup the stack +: lda $0100,x + jsr IECOUT + inx + bne :- + + ; Backup the colour RAM +: lda $DA00,x ; Color RAM + jsr st_high_nibble + lda $D800,x ; Color RAM + jsr st_low_nibble + inx + bne :- +: lda $DB00,x ; Color RAM + jsr st_high_nibble + lda $D900,x ; Color RAM + jsr st_low_nibble + inx + bne :- + + ; Backup VIC-II registers +: lda $D000,x ; Position X sprite 0 + jsr IECOUT + inx + cpx #$2F + bne :- + + ; Backup $0400..$0402 + ldx #$00 +: lda $0400,x ; Video matrix (25*40) + jsr IECOUT + inx + cpx #$03 + bne :- + + jsr file_close_ch1 + + sei + + ; Install the zp_load_mem* routines into zeropage + ldx #<__zp_load_mem_1_SIZE__-1 +: lda __zp_load_mem_1_LOAD__,x + sta __zp_load_mem_1_RUN__,x + dex + bpl :- + + ; Backup $FFFD..$FFFF + lda #<$FFFD + sta tmpptr_a + lda #>$FFFD + sta tmpptr_a+1 + ldy #$02 + lda #$33 + sta $01 +: jsr zp_load_tmpptr_a + sta $009B,y + dey + bpl :- + + ; Compress the memory + jsr backup_compress_ram + lda $99 + sta tmpptr_a + lda $9A + sta tmpptr_a+1 + + ldx #<__zp_load_mem_2_SIZE__-1 +: lda __zp_load_mem_2_LOAD__,x + sta __zp_load_mem_2_RUN__,x + dex + bpl :- + + lda tmpptr_a + sta $96 + lda tmpptr_a+1 + sta $97 + sec + lda #$00 + sbc tmpptr_a + sta $9E + lda #$00 + sbc tmpptr_a+1 + clc + adc #$04 + sta $9F + ldx #$37 + stx $01 + + + jsr open_minusfc + ldx #$00 + + ; Backup page $0200 +: lda $0200,x + jsr IECOUT + inx + bne :- + + ; Backup page $0300 +: lda $0300,x + jsr IECOUT + inx + bne :- + + ; X=0 + ; Backup some variables +: lda $9B,x + jsr IECOUT + inx + cpx #$05 + bne :- + + ldy #<$0400 + sty tmpptr_a + lda #>$0400 + sta tmpptr_a+1 +@3: jsr $00A6 + jsr IECOUT + inc tmpptr_a + bne :+ + inc tmpptr_a+1 +: lda tmpptr_a + cmp $96 + lda tmpptr_a+1 + sbc $97 + bcc @3 + jsr file_close_ch1 + ldy #$0A + jsr set_1541_sector_interleave + jmp write_mg87_and_reset + + +.segment "backup_disk_2" + +st_high_nibble: + asl + asl + asl + asl + sta $A5 + rts + +st_low_nibble: + and #$0F + ora $A5 + jmp IECOUT + +open_fc: + lda #$F1 ; OPEN channel 1 + jsr listen_second + jmp send_fc + +open_minusfc: + lda #$F1 + jsr listen_second + lda #$2D + jsr IECOUT +send_fc: + lda #'F' + jsr IECOUT + lda #'C' + jsr IECOUT + jsr UNLSTN + lda #$61 ; LISTEN channel 1 +listen_second: + pha + lda #$08 + jsr LISTEN + pla + jmp SECOND + +; +; Set 1541 sector interleave to value in Y +; +.proc set_1541_sector_interleave + lda #$6F ; Talk to channel 15 + jsr listen_second + ldx #sizeof_interleave_write - 1 +: lda interleave_write,x + jsr IECOUT + dex + bpl :- + tya + jsr IECOUT + jmp UNLSTN +.endproc + +interleave_write: .byte $01,$00,$69,'W','-','M' +sizeof_interleave_write = .sizeof(interleave_write) + +file_close_ch1: + jsr UNLSTN + lda #$e1 + jsr listen_second ; Close channel 1 + jmp UNLSTN + + + sei + lda #$33 + sta $01 + ldy #$00 + sty $C3 + lda #$01 + sta $C4 + tya +: sta ($C3),y + iny + bne :- + inc $C4 + bne :- + lda #$37 + sta $01 + jmp START ; KERNAL RESET routine + +.segment "backup_compress" + +; +; Compress the C64's memory from $0403 to $FFFD using Run Length Encoding +; +; +; Compressed stream opcodes: +; +; $00 nn aa bb cc ... Copy $nn bytes to output (<256 bytes) +; $01 nn oo aa bb cc ... Copy $oonn bytes to output (>=256 bytes) +; $02 oo nn xx Copy a run of $oonn bytes with value xx to output (<256 bytes) +; nn xx (nn>$02) Copy a run of $nn bytes with value xx to output (>=256 byte) + + +backup_compress_ram: + lda #>$0403 ; RAM compression starts at $0403 + sta $97 + sta tmpptr_a+1 + sta $9A + ldy #$00 + sty $99 + lda #<$0403 ; RAM compression starts at $0403 + sta $96 ; Source ptr1 + sta tmpptr_a ; Source ptr2 + ldy #$00 + ldx #$00 + ; Find at least 4 equal bytes in sequence +@find_run_of_4: + ldy #$00 + jsr zp_load_96 ; Load a byte from RAM + sta $98 ; Open files number/Index of files table +: iny + jsr zp_load_96 ; Load another byte from RAM + cmp $98 ; Same as previous? + bne @1 + cpy #4 + bne :- + beq @found4 +@1: jsr incptrchkend + bcc @find_run_of_4 ; Not end of memory? Then continue +@found4: + ldy #$00 + ldy #$00 + ; Compute the different between $96/$97 and tmpptr_a and store in $98 + sec + lda $96 + sbc tmpptr_a + tax + lda $97 + sbc tmpptr_a+1 + sta $98 + bne @st_big_unmodified + txa + beq @count_run ; Jump if low bytes equal + ; Store <256 bytes up until the run unmodified + lda #$00 + jsr zp_store_a_99 + txa + jsr zp_store_a_99 +@2: jsr zp_load_tmpptr_a_inc_ptr2 + jsr zp_store_a_99 + dex +@6: bne @2 + jsr chkend + bcc @count_run + rts + ; Store >=256 bytes up until the run unmodified +@st_big_unmodified: + lda #$01 + jsr zp_store_a_99 + txa + pha + jsr zp_store_a_99 + lda $98 + jsr zp_store_a_99 + ldx #$00 +: jsr zp_load_tmpptr_a_inc_ptr2 + jsr zp_store_a_99 + inx + bne :- + dec $98 + bne :- + pla + tax + clc + bcc @6 +@count_run: + jsr zp_load_96 + sta $98 +: jsr incptrchkend + bcs :+ + jsr zp_load_96 + cmp $98 + beq :- +: ; Compute the length of the run + sec + lda $96 + sbc tmpptr_a + tax + lda $97 + sbc tmpptr_a+1 + pha + + ; Copy $96/$97 into tmpptr_a + lda $96 + sta tmpptr_a + lda $97 + sta tmpptr_a+1 + + pla + bne @stbigrun + txa +@stsmallrun: + jsr zp_store_a_99 + lda $98 + jsr zp_store_a_99 + jsr chkend + bcs _rts + jmp @find_run_of_4 + +@stbigrun: + pha + lda #$02 + jsr zp_store_a_99 + txa + jsr zp_store_a_99 + pla + bne @stsmallrun + +incptrchkend: + inc $96 + bne chkend + inc $97 +chkend: + lda $96 + cmp #<$FFFD + lda $97 + sbc #>$FFFD + ; This will underflow if $96/$97 < $FFFD, thus C=1 if at end of memory. +_rts: + rts + +.proc zp_store_a_99 + sta ($99),y + inc $99 + bne :+ + inc $9A +: rts +.endproc + +.proc zp_load_tmpptr_a_inc_ptr2 + jsr zp_load_tmpptr_a + inc tmpptr_a + bne :+ + inc tmpptr_a+1 +: rts +.endproc + +.segment "zp_load_mem_1" + +.proc zp_load_96 + inc $01 + lda ($96),y + dec $01 + rts +.endproc + +.proc zp_load_tmpptr_a + inc $01 + lda (tmpptr_a),y + dec $01 + rts +.endproc + + +.segment "zp_load_mem_2" + +.proc zp_load_tmpptr_b + lda #$0C + sta $01 + lda (tmpptr_a),y + pha + lda #$0F + sta $01 + pla + rts +.endproc + +.segment "disk_backup_loader" + +.incbin "disk_backload/backup_loader.prg" + + +.segment "freezer_backup_tape" + +turbotape_tape_program_header: + .word $0801 ; Load address of program + .word $105a ; End address of program + .byte $00 + .byte "FC" + +.global freezer_backup_tape + +freezer_backup_tape: + lda #$00 ; Disable all sprites + sta $D015 + lda #<__tape_backup_loader_LOAD__ + sta tmpptr_a + lda #>__tape_backup_loader_LOAD__ + sta tmpptr_a+1 + jsr tape_prepare + + jsr tape_write_header_fast ; Sets Y=0 + lda #$01 ; Indicates that we are writing a BASIC program to tape + jsr tape_write_byte_fast + ldx #$08 +: lda turbotape_tape_program_header,y + jsr tape_write_byte_fast + ldx #$07 ; Reload pulse length + iny + cpy #$07 ; 8 bits written? + bne :- ; No, then loop + ldy #$00 +: lda #$20 ; Write the value $20 $B8 times to fill the header + jsr tape_write_byte_fast + ldx #$07 ; Reload pulse length + iny + cpy #$B9 ; $B8 times + bne :- + + ; Write the loader to tape + jsr tape_write_header_fast ; Write another header ; sets Y=0 + tya + jsr tape_write_byte_fast ; Write a 0 byte + ldx #$07 ; Reload pulse length +@1: lda (tmpptr_a),y ; Get a byte from the loader + jsr tape_write_byte_fast + ldx #$03 ; Reload pulse length (compensated for extra instructions) + inc tmpptr_a ; Increase low byte of pointer + bne :+ ; Next byte + inc tmpptr_a+1 ; Increase high byte of pointer + dex ; Compensate for extra instructions + dex +: lda tmpptr_a + cmp #<(__tape_backup_loader_LOAD__ + __tape_backup_loader_SIZE__) + lda $92 + sbc #>(__tape_backup_loader_LOAD__ + __tape_backup_loader_SIZE__) + bcc @1 + + ; Write the zeropage to tape + ldx #$02 +: lda $0000,y + jsr tape_write_byte_fast + ldx #$07 + iny + bne :- + + ; Write the stack to tape +: lda $0100,y + jsr tape_write_byte_fast + ldx #$07 + iny + bne :- + + ; Write the colour RAM to tape + sty tmpptr_a ; Y already 0 + lda #$D8 ; $D800 + sta tmpptr_a+1 + ldx #$04 +: lda (tmpptr_a),y ; Load a byte from colour RAM + jsr tape_write_byte_fast + ldx #$08 + iny + bne :- + ldx #$03 + inc tmpptr_a+1 + lda tmpptr_a+1 + cmp #$DC ; End of colour RAM ? + bne :- + + ; Save the VIC-II registers to tape +: lda $D000,y + jsr tape_write_byte_fast + ldx #$07 + iny + cpy #$2F + bne :- + + ; Save $0400..$0402 to tape + ldy #$00 +: lda $0400,y ; Video matrix (25*40) + jsr tape_write_byte_fast + ldx #$07 + iny + cpy #$03 + bne :- + + ; Save checksum to tape + lda $A4 + inx + jsr tape_write_byte_fast + jsr tape_finnish + + ; Install the zp_load_mem* routines into zeropage + ldx #<__zp_load_mem_1_SIZE__-1 +: lda __zp_load_mem_1_LOAD__,x + sta __zp_load_mem_1_RUN__,x + dex + bpl :- + + ; Retrieve the vectors from $FFFD + ldy #$02 + lda #<$FFFD + sta tmpptr_a + lda #>$FFFD + sta tmpptr_a+1 + lda #$33 + sta $01 +: jsr zp_load_tmpptr_a + sta $009B,y + dey + bpl :- + + jsr backup_compress_ram + lda $99 + sta tmpptr_a + lda $9A + sta tmpptr_a+1 + + ldx #<__zp_load_mem_2_SIZE__-1 +: lda __zp_load_mem_2_LOAD__,x + sta __zp_load_mem_2_RUN__,x + dex + bpl :- + + lda tmpptr_a + sta $96 + lda tmpptr_a+1 + sta $97 + + ; Negate tmpptr_a, add $0400 and store in $9e/$9f + sec + lda #0 + sbc tmpptr_a + sta $9E + lda #0 + sbc tmpptr_a+1 + clc + adc #$04 + sta $9F + + lda #$37 + sta $01 + jsr tape_prepare + sty tmpptr_a + lda #$04 + sta tmpptr_a+1 + + ; Write a turbo tape header + jsr tape_write_header_fast + tya + jsr tape_write_byte_fast + ldx #$08 +: lda $009B,y + jsr tape_write_byte_fast + ldx #$06 + iny + cpy #$05 + bne :- + + ; Backup the compressed memory + ldy #$00 + ldx #$07 +@2: jsr zp_load_tmpptr_b + sta tmpvar1 + lda #$08 + sta $A3 +: asl tmpvar1 + lda $01 + and #$F7 + jsr tape_half_pulse + ldx #$11 + ora #$08 + jsr tape_half_pulse + ldx #$0E + dec $A3 + bne :- + ldx #$03 + inc tmpptr_a + bne :+ + dex + dex + inc tmpptr_a+1 +: lda tmpptr_a + cmp $96 + lda tmpptr_a+1 + sbc $97 + bcc @2 + + jsr tape_finnish + + lda #$37 + sta $01 + jsr tape_prepare + jsr tape_write_header_fast + tya + jsr tape_write_byte_fast + ldx #$08 + + ; Write the $0200 page +: lda $0200,y + jsr tape_write_byte_fast + ldx #$07 + iny + bne :- + + ; Write the $0300 page +: lda $0300,y + jsr tape_write_byte_fast + ldx #$07 + iny + bne :- + jsr tape_finnish + + jmp write_mg87_and_reset + + +; +; Wait for a button press on tape, disable the screen and start the tape motor +; +tape_prepare: + lda #$10 ; Bit 4 is cassette sense +: bit $01 + bne :- ; Not presset? Then loop + lda $01 + and #$07 ; Enable tape motor + sta $01 + lda #$0B + sta $D011 ; Disable screen (normal value of $d011 is $1b) + ldy #0 ; Do a delay loop, because VIC-II only stops bad lines +: inx ; at the next frame. + bne :- + iny + bne :- + rts + +; +; Enable the screen, and stop the tape motor +; +tape_finnish: + lda #$1B ; Enable screen + sta $D011 + lda $01 + ora #$20 ; Bit 5 is tape motor + sta $01 + rts + +; +; Write the Turbotape header to tape. A Turbotape header consists of 256 times the value +; 2. This is the pilot tone that allows synchronization. However, the following routine +; writes 5 * 247 times a 2, so the header is longer than the original turbotape program. +; Then the bytes 9,8,7,6,5,4,3,2,1 are written. This allows the reader to differentiate +; between a valid header and not just some random sequence of twos. +; +; Y=0 on return, code depends on this. +; + +tape_write_header_fast: + lda #$05 ; 5 times 247 + sta $A5 + ldy #$00 ; Start at 0 and count down +: lda #$02 ; Write a 2 to tape + jsr tape_write_byte_fast + ldx #$07 ; Lenth of the low pase + dey + cpy #$09 ; Did we write 247 bytes? + bne :- ; No, then loop + ldx #$05 ; Length of the low phase (slightly lower because + ; we did exec more instructions). + dec $A5 + bne :- +: tya + jsr tape_write_byte_fast + ldx #$07 ; Length of the low phase + dey + bne :- + dex ; Length of low phase to to 5 to account for extra + ; instructions + dex + sty $A4 ; Y=0 + rts + + + + ldx #$08 +; +; Write the byte in A to tape +; +tape_write_byte_fast: + sta tmpvar1 ; Store the byte to write + eor $A4 ; Update checksum + sta $A4 + lda #8 ; 8 Bits to write + sta $A3 +: asl tmpvar1 ; Shift a bit out + lda $01 + and #$F7 ; Write the low pulse phase + jsr tape_half_pulse + ldx #17 ; Length of pulse + ora #$08 ; Write the high pulse phase + jsr tape_half_pulse + ldx #14 ; Length of pulse + dec $A3 ; Count down number of bits + bne :- ; More bits to write? Then loop. + rts + +; +; Do either the high or low phase of the pulse. +; C contains the bit to write to tape +; 0 = 176 us pulse +; 1 = 256 us pulse +; +; A contains the value to write to $01, either bit 3 set or reset depending +; on wheter to write the high or low phase. +; +tape_half_pulse: +: dex + bne :- + bcc @1 + ldx #$0B +: dex + bne :- +@1: sta $01 + rts + +.segment "tape_backup_loader" + +.incbin "tape_backload/backup_loader.prg",2 + diff --git a/bank3/freezer_entry.s b/bank3/freezer_entry.s new file mode 100644 index 0000000..d67b35b --- /dev/null +++ b/bank3/freezer_entry.s @@ -0,0 +1,825 @@ +;***************************************************************************** +; Final Cartridge III reconstructed source code +; +; The NMI interruprs handler that is executed in Ultimax mode, switches +; back to 16K mode and then calls freezer_init in this file. Here the actual +; freezing is done, then the routine to display the menu is called. The +; menu code is not inside this file. +; +; After the user has made a selction from the file menu, control is returned +; to this file and a jump is made to the routine that executes the command. +;***************************************************************************** + + .setcpu "6502x" + +.include "../core/kernal.i" +.include "../core/fc3ioreg.i" +.include "persistent.i" + +.import _jmp_bank,_enable_fcbank0,_disable_fc3rom_set_01 +.import freezer_set_c64and_fc3_rts +.import freezer_ultimax_exec_menu +.import autofire_lda_dc01,autofire_ldx_dc01,autofire_ldy_dc01 +.import autofire_lda_dc00,autofire_ldx_dc00,autofire_ldy_dc00 +.import __romio2l_RUN__ +.importzp __FREEZERZP_START__,__FREEZERZP_SIZE__ +.import __tape_backup_loader_LOAD__,__tape_backup_loader_SIZE__ +.import __disk_backup_loader_LOAD__,__disk_backup_loader_SIZE__ +.import __zp_load_mem_1_LOAD__,__zp_load_mem_1_SIZE__ +.import __zp_load_mem_2_LOAD__,__zp_load_mem_2_SIZE__ +.importzp __zp_load_mem_1_RUN__,__zp_load_mem_2_RUN__ +.import __freezer_restore_1_LOAD__,__freezer_restore_1_SIZE__ +.import __freezer_restore_2_RUN__,__freezer_restore_2_SIZE__ +.import __memswap_LOAD__ +.importzp __memswap_RUN__,__memswap_SIZE__ +.import pset +.import freezer_goto_settings,freezer_zero_fill,write_mg87_and_reset +.import freezer_sprite_I,freezer_sprite_II,freezer_autofire,freezer_joyswap +.import freezer_backup_disk,freezer_backup_tape +.import freezer_goto_monitor + +.segment "freezer_zeropage":zeropage + +.global tmpptr_a,tmpvar1,spritexy_backup +.global freezer_mem_a,freezer_mem_a_val,freezer_mem_b,freezer_mem_b_val +.global spritexy_backup,viciireg_backup,colram_backup,ciareg_backup + +ciareg_backup: .res 32 +tmpvar1: .res 1 +tmpptr_a: .res 2 +tmpvar2: .res 1 +spritexy_backup: .res 8 ; Backup sprite 2..5 x/y coord ($D004..$D00B) +viciireg_backup: .res 25 ; VIC-II registers from $D010 +spritecol_backup: .res 4 +spriteptr_backup: .res 4 +colram_backup: .res 16 ; Back for last 16 bytes of 1st line of colour RAM +zp2345_backup: .res 4 +freezer_mem_a: .res 2 +freezer_mem_a_val: .res 1 +freezer_mem_b: .res 2 +freezer_mem_b_val: .res 1 + +.segment "freezer_entry_1" + +.global freezer_init +freezer_init: + ; Install loadram, routine at $0005 + ldx #$06 +: lda loadram,x + sta $05,x + dex + bpl :- + ldx $02A0 + inx + cpx $02A2 + bne :+ + inx +: stx $02A1 + ldx #<$E000 + lda #>$E000 + ldy #__FREEZERZP_SIZE__ ; Find some memory for zero page backup + jsr freezer_find_memory + lda $02 + clc + adc #__FREEZERZP_SIZE__ + tax + lda $03 + adc #$00 + ldy #<__freezer_restore_1_SIZE__ + jsr freezer_find_memory + ; + ; THis is a bit of a weird method... location of first memory region + ; was not save, so the same block of memory again. + ; + ldx #<$E000 + lda #>$E000 + ldy #__FREEZERZP_SIZE__ + jsr freezer_find_memory + ldy #$00 + ; Backup the zeropage area that the freezer will use into the found memory +: lda __FREEZERZP_START__,y ; Lo Byte #1 (rounding) + sta ($02),y + iny + cpy #<__FREEZERZP_SIZE__ + bne :- + + lda $02 ; Low byte of found memory + sta freezer_mem_a ; keep it for later + lda $03 ; High byte of found memory + sta freezer_mem_a+1 ; keep it for later + lda $04 ; value of the found memory + sta freezer_mem_a_val ; keep it for later + + ; Save the NMI vector on the stack + lda $0318 ; Vector: Not maskerable Interrupt (NMI) + pha + lda $0319 ; Vector: Not maskerable Interrupt (NMI) + pha + lda #temp_nmi_handler + sta $0319 ; Vector: Not maskerable Interrupt (NMI) + + ; Backup the contents of the CIA registers and initalize them with correct + ; values for the freezer. + ldx #$1F +@nextreg: + lda $DCF0,x ; Backup the cia registers + sta ciareg_backup,x + txa + and #$0F + cmp #$02 ; Is it a port DATA register? + bcc @dec_loop ; Yes, then no backup + cmp #$04 ; Not port data nor ddr register? + bcs @1 ; Then jump to further register tests + lda #$FF ; Initialize DDRs with $ff + sta $DCF0,x + bne @dec_loop +@1: + cmp #$0E ; Is it a timer control register? + bcc @2 ; Then jump to further register tests + lda #$10 ; Initialize control register with $10 + sta $DCF0,x +@2: + cmp #$08 ; Is it a timer value ? + bcs @dec_loop ; No, then go on + cmp #$04 ; Is it a timer value ? + bcc @dec_loop ; No, then go on + and #$01 ; Init both timers with $0001 + eor #$01 + sta $DCF0,x +@dec_loop: + dex + bpl @nextreg + + ; Clear interrupt flags of both CIAs by reading from their ICR + ldx #$00 + lda $DCFD,x + ldx #$10 + lda $DCFD,x + + ; The interrupt mask inside the ICR of the CIA cannot be read, because reading the + ; register has a different meaning. Both CIA's won't be restored on return, but cleared + lda #0 + sta ciareg_backup + $0d + sta ciareg_backup + $1d + + ; Handle CIA timers... + ldx #$01 ; Start with timer B +@nexttimer: + ; Start the timer in one shot mode on both CIAs + lda #$19 + sta $DC0E,x ; Control register A of CIA #1 + sta $DD0E,x ; Control register A of CIA #2 + + txa + pha ; Push timer number + asl ; Timer number *2 + bne @3 ; Jump if timer A + lda #$01 +@3: + sta tmpvar2 ; 1 for timer A, 2 for timer B + ldx #0 + .byte $2c ; bit $xxxx, skip next instruction +@nextcia_1: + ldx #$10 +@4: lda $DCFD,x ; load ICR + tay + and tmpvar2 ; Wait for timer underflow + beq @4 + tya + bpl @5 ; Interrupt occured? No, then @5 + ora $7D,x ; OR ISR into $7D/8D + sta $7D,x +@5: dex + bmi @nextcia_1 + pla ; Restore cia number + tax + dex + bpl @nexttimer + + ; Delay loop + ldy #0 +@6: inx + bne @6 + iny + bne @6 + + ; X=0 + .byte $2c ; bit $xxxx, skip next instruction +@nextcia_2: + ldx #$10 + lda #$7F ; Disable all interrupt sources + sta $DCFD,x + ldy ciareg_backup + $D,x ; Did an interrupt occur + bmi @7 ; Then skip + lda #$7F + sta ciareg_backup + $D,x +@7: dex + bmi @nextcia_2 + + ; Restore the NMI vector + pla + sta $0319 + pla + sta $0318 ; Vector: Not maskerable Interrupt (NMI) + + ; Value of $dd0e/$dd0f was pushed on stack by NMI handler and set to 0 + ; before the CIA registers could be backed up, so correct this: + pla + sta ciareg_backup + $1f + pla + sta ciareg_backup + $1e + + lda $04 ; Value in found memory area + pha ; Save for later + lda $02 ; Lo byte of found memory area + pha ; Save for later + clc + adc #$67 + tax + lda $03 ; Lo byte of found memory area + pha ; Save for later + adc #$00 + ; A/X now points to end of found memory area + ldy #<__freezer_restore_1_SIZE__ + jsr freezer_find_memory ; Find another memory area of $5c bytes + lda $02 + sta freezer_mem_b ; Store high byte of area + lda $03 ; + sta freezer_mem_b+1 ; Store low byte of area + lda $04 ; Value found in memory area + sta freezer_mem_b_val ; Save for later + + ; Install the freezer restore routine in the second memory area found and + ; do live patching. + ldy #<__freezer_restore_1_SIZE__ - 1 +: lda freezer_restore_mem_cia_vic,y + sta ($02),y + dey + bpl :- + + ; Do some live patching of the freezer restore routine + pla + ldy #<(r1 + 2 -__freezer_restore_1_LOAD__) + sta ($02),y + ldy #<(r2 + 2 -__freezer_restore_1_LOAD__) + sta ($02),y + pla + dey + sta ($02),y + ldy #<(r1 + 1 -__freezer_restore_1_LOAD__) + sta ($02),y + pla + ldy #<(r3 + 1 -__freezer_restore_1_LOAD__) + sta ($02),y + pla + sta tmpptr_a + pla + sta tmpptr_a+1 + + lda $04 + tay + ldx #$FF +: inx + pla + sta $04,x + cpx #8 + bne :- + ; C=1 because X=8 + + tya + tax + pla + ldy #<(r4 + 1 -__freezer_restore_1_LOAD__) + sta ($02),y + pla + ldy #<(r5 + 1 -__freezer_restore_1_LOAD__) + sta ($02),y + txa + ldy #<(r6 + 1 -__freezer_restore_1_LOAD__) + sta ($02),y + + ; The freezer restore routine will RTS to the + ; current stack pointer - #$12 + ; C is still 1 + tsx + lda #$01 + pha + txa + sbc #$12 + pha + + ; Patch loading the original value of the stack pointer + tsx + txa + ldy #<(r7 + 1 -__freezer_restore_1_LOAD__) + sta ($02),y + + ; Push a small routine on the stack that will overwrite + ; the restore routine with the original value. + ldx #(START-1) + pha + lda #<(START-1) + pha + jmp _enable_fcbank0 + +freezer_final_kill: + ; Jump to RESET vector in KERNAL + lda #>(START-1) + pha + lda #<(START-1) + pha + ; ROM bank 0, C64 in normal mode, NMI line released and disable FC3 hardware: + lda #fcio_bank_0|fcio_c64_crtrom_off|fcio_nmi_line|fcio_kill + jmp _jmp_bank + +freezer_pset: + jsr call_pset_in_bank0 + jmp freezer_run + +call_pset_in_bank0: + lda #>pset + pha + lda #=$e000. If yes, the screen + ; ram is used as freezer memory. If no, the stack is used as a last resort. + ; + ; The first $C3 bytes of the screen buffer or stack is cleared, which is + ; mysterious as well, since if consecutive bytes are found, nothing is + ; cleared + ; + lda $D018 ; VIC memory control register + and #$F0 + lsr + lsr + sta $03 ; Jump Vector: real-integer conversion + lda $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + and #$03 + eor #$03 + lsr + ror + ror + ora $03 ; Jump Vector: real-integer conversion + cmp #$D0 + bcc @screen_ok + cmp #$E0 + bcs @screen_ok + lda #$01 ; Use stack as last resort +@screen_ok: + sta $03 + ldy #0 + sty $02 ; Low byte to zero + tya +: sta ($02),y ; Clear the byte + iny + cpy #$C3 ; End reached? + bne :- +@exit: + lda #$37 ; Normal memory config + sta $01 + rts + +.segment "freezer_entry_3" + +loadram: + ; $01 contains $33 i.e. BASIC CHARROM KERNAL visble + inc $01 ; $01 contains $34, 100% RAM + lda ($02),y + dec $01 ; re-enable ROM + rts +temp_nmi_handler: + rti diff --git a/bank3/freezer_game.s b/bank3/freezer_game.s new file mode 100644 index 0000000..b2a98f9 --- /dev/null +++ b/bank3/freezer_game.s @@ -0,0 +1,265 @@ +;***************************************************************************** +; Final Cartridge III reconstructed source code +; +; This file implements the functions of the game menu of the freezer +;***************************************************************************** + + .setcpu "6502x" + +.include "../core/kernal.i" +.include "../core/fc3ioreg.i" +.include "persistent.i" + +.import _jmp_bank,_enable_fcbank0,_disable_fc3rom_set_01 +.import freezer_set_c64and_fc3_rts +.import freezer_ultimax_exec_menu +.import autofire_lda_dc01,autofire_ldx_dc01,autofire_ldy_dc01 +.import autofire_lda_dc00,autofire_ldx_dc00,autofire_ldy_dc00 +.import __romio2l_RUN__ +.importzp __FREEZERZP_START__,__FREEZERZP_SIZE__ +.import __tape_backup_loader_LOAD__,__tape_backup_loader_SIZE__ +.import __disk_backup_loader_LOAD__,__disk_backup_loader_SIZE__ +.importzp __zp_load_mem_1_RUN__,__zp_load_mem_2_RUN__ +.import __freezer_restore_1_LOAD__,__freezer_restore_1_SIZE__ +.import __freezer_restore_2_RUN__,__freezer_restore_2_SIZE__ +.import __memswap_LOAD__ +.importzp __memswap_RUN__,__memswap_SIZE__ +.importzp tmpptr_a,tmpvar1 + +.segment "freezer_game_swap" + +swap_8000_4000: + ldy #$80 ; Swap from $8000 + .byte $2c ; bit $xxxx (3 byte nop) +swap_c000_4000: + ldy #$c0 + ldx #__memswap_SIZE__-1 +: lda __memswap_LOAD__,x + sta __memswap_RUN__,x + dex + bpl :- + sty <(swap_zpcode_ptr2+1) + ldx #$40 ; Number of pages + lda #$34 ; Hide ROM + ldy #$00 + sei + jmp swap_zpcode + +.segment "memswap":zeropage +.proc swap_zpcode + sta $01 +: lda (ptr1),y ; load a byte from $4000+ + pha ; and save to stack + lda (ptr2),y ; load a byte from $8000+ or $c000+ + sta (ptr1),y ; store into $4000x + pla ; restore saved byte + sta (ptr2),y ; save into $8000+ or $c000+ + iny ; inc low byte + bne :- + inc <(ptr1+1) ; inc high byte of $4000 pointer + inc <(ptr2+1) ; inc high byte of $8000/$c000 pointer + dex ; dec page counter + bne :- ; loop until all pages have been swapped + lda #$37 ; BASIC, KERNAL and IO visible + sta $01 + rts +ptr1: .word $4000 +ptr2: .word $8000 +.endproc + +swap_zpcode_ptr2 = swap_zpcode::ptr2 ; Necessary because ca65 only knows scope after it has been defined. + +.segment "freezer_game" + + ; These are the opcodes for + ; lda absolute + ; ldx absolute + ; ldy absolute + ; lda absolute,x + ; lda absolute,y +load_abs_opcodes: .byte $ad,$ae,$ac,$bd,$b9 + + ; These are the opcodes for + ; lda #imm + ; ldx #imm + ; ldy #imm +load_imm_opcodes: .byte $a9,$a2,$a0 +autofire_traps: + .byte __romio2l_RUN__ ; $DFxx + sta (tmpptr_a),y ; Patch into instruction +@4: + inc tmpptr_a ; inc low byte of pointer + bne @1 + inc tmpptr_a+1 ; inc high byte of pointer + lda tmpptr_a+1 + cmp #$80 ; cartridge rom starts at $8000 + bcc @1 ; when we arrive here, stop scanning + rts + +joyswap_patch_code_0200: + lda #$02 ; High byte of start pointer + .byte $2c ; bit $xxxx (3 byte nop) +joyswap_patch_code_4000: + lda #$40 ; High byte of start pointer + sta tmpptr_a+1 + lda #$00 ; Low byte of start pointer + sta tmpptr_a +@1: ldx #$03 ; Check 3 opcodes + ldy #0 + lda (tmpptr_a),y ; Load a byte from RAM +@2: dex + bmi @3 + cmp load_abs_opcodes,x + bne @2 + iny + lda (tmpptr_a),y ; Load next byte from RAM (should be low byte of absolute address) + sta tmpvar1 ; Store low byte + cmp #$04 + bcs @3 + iny + lda (tmpptr_a),y ; Load next byte from RAM (should be high byte of absolute address) + cmp #$DC ; $DCxx is CIA 1 + bne @3 + dey + lda tmpvar1 ; Restore low byte + eor #$01 ; Swap $dc01 with $dc00 to swap joystick port + sta (tmpptr_a),y ; Patch into instruction +@3: inc tmpptr_a + bne @1 + inc tmpptr_a+1 + lda tmpptr_a+1 + cmp #$80 ; cartridge rom starts at $8000 + bcc @1 ; when we arrive here, stop scanning + rts + +sprite_patch_code_0200: + lda #$02 ; High byte of start pointer + .byte $2c ; bit $xxxx (3 byte nop) +sprite_patch_code_4000: + lda #$40 ; High byte of start pointer + sta tmpptr_a+1 + lda #$00 ; Low byte of start pointer + sta tmpptr_a +@1: ldx #$03 ; Check 3 opcodes + ldy #0 + lda (tmpptr_a),y ; Load a byte from RAM +@2: dex + bmi @4 + cmp load_abs_opcodes,x + bne @2 + iny + lda (tmpptr_a),y ; Load next byte from RAM (should be low byte of absolute address) + cmp tmpvar1 ; Is low byte the relevant sprite collision register? + bne @4 +@3: iny + lda (tmpptr_a),y ; Load next byte from RAM (should be high byte of absolute address) + cmp #>$D000 ; $D0xx is VIC-II + bne @4 + lda load_imm_opcodes,x + ldy #0 + sta (tmpptr_a),y ; Patch opcode into memory + tya + iny + sta (tmpptr_a),y ; Change into LDx #0 + lda #$EA ; NOP + iny + sta (tmpptr_a),y ; Place nop in memory +@4: inc tmpptr_a + bne @1 + inc tmpptr_a+1 + lda tmpptr_a+1 + cmp #$80 + bcc @1 + rts + diff --git a/bank3/freezer_menu.s b/bank3/freezer_menu.s new file mode 100644 index 0000000..276f2c8 --- /dev/null +++ b/bank3/freezer_menu.s @@ -0,0 +1,1784 @@ +;***************************************************************************** +; Final Cartridge III reconstructed source code +; +; This file contains the NMI interrupt handler for the frezer. The actual +; NMI occurs in bank 0, but the NMI handler is duplicated in both banks and +; the NMI handler in bank 0 quickly changes to bank 3 to continue. +; +; This file also contains the graphics and code for the freezer menu and +; the graphics and code for the screenshot preview function in the freezer. +; +;***************************************************************************** + + .setcpu "6502x" + +.include "persistent.i" +.include "../core/fc3ioreg.i" + +.importzp ciareg_backup +.importzp viciireg_backup +.importzp spritexy_backup +.importzp colram_backup + + .macro MonoSpriteLine tribyte + .byte tribyte >> 16, ( tribyte >> 8) & 255, tribyte & 255 + .endmacro + +freezer_prepare = $DFE0 + +.segment "freezer_graphics" + +freezer_screenram: + .byte 5, 6, 7, 8, 9, 10, 11, 12 + .byte 13, 14, 15, 16, 17, 18, 19, 20 + .byte 21, 22, 23, 24, 25, 26, 27, 28 + .byte 29, 30, 31, 32, 33, 34, 35, 36 + .byte 37, 38, 39, 11, 11, 11, 11, 11 +; ▉▉▉░░░░▉▉▉▉░░▉▉▉▉░░░▉▉░▉▉▉░▉░▉▉▉░▉░░░░▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉░▉▉▉░▉▉░▉▉░▉▉░▉▉▉░▉░▉▉░▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉▉▉▉ +; ▉▉▉░▉▉▉░▉░▉▉▉▉░▉░▉▉▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉▉▉▉ +; ▉▉▉░░░░▉▉░▉▉▉▉░▉░▉▉▉▉▉░░▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉▉▉▉ +; ▉▉▉░▉▉▉░▉░░░░░░▉░▉▉▉▉▉░▉░▉▉▉░▉▉▉░▉░░░░▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉░▉▉▉░▉░▉▉▉▉░▉░▉▉▉░▉░▉▉░▉▉░▉▉▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉░░░░▉▉░▉▉▉▉░▉▉░░░▉▉░▉▉▉░▉▉░░░░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ +freezer_bar_charset: + .byte %11100001, %11101110, %11101110, %11100001, %11101110, %11101110, %11100001, %11111111 + .byte %11100111, %11011011, %10111101, %10111101, %10000001, %10111101, %10111101, %11111111 + .byte %10001101, %01110101, %01111101, %01111100, %01111101, %01110101, %10001101, %11111111 + .byte %11010111, %10110111, %01110111, %11110111, %01110111, %10110111, %11011000, %11111111 + .byte %01000011, %01011101, %01011101, %01011101, %01000011, %01011111, %01011111, %11111111 + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 +; ▉▉▉▉▉▉▉▉▉▉▉▉░░░▉▉▉▉░░▉▉▉░▉▉▉▉▉░▉░░░░▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉▉░▉▉░▉▉░░▉▉▉░░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉▉░▉▉▉▉░▉░▉░▉░▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉░░▉░▉▉▉▉░▉░▉▉░▉▉░▉░░░▉▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░░░░░░▉░▉▉▉▉▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉▉░▉░▉▉▉▉▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉░░░▉▉░▉▉▉▉░▉░▉▉▉▉▉░▉░░░░▉▉▉▉▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + .byte %11110001, %11101110, %11101111, %11101100, %11101110, %11101110, %11110001, %11111111 + .byte %11100111, %11011011, %10111101, %10111101, %10000001, %10111101, %10111101, %11111111 + .byte %01111101, %00111001, %01010101, %01101101, %01111101, %01111101, %01111101, %11111111 + .byte %00001111, %01111111, %01111111, %00011111, %01111111, %01111111, %00001111, %11111111 + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 +; ▉▉▉▉▉▉▉▉▉▉▉▉░░░▉▉▉░░░▉▉░▉▉▉▉░░░▉▉░░░░▉▉▉░░░░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉▉░▉▉░░░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░░░░▉▉▉▉▉▉░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉░▉▉▉▉▉▉░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉░░░▉▉▉░░░▉▉░░░▉▉░░░▉▉░▉▉▉░▉░░░░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + .byte %11110001, %11101110, %11101111, %11101111, %11101111, %11101110, %11110001, %11111111 + .byte %11000110, %10111010, %10111010, %10111010, %10111010, %10111010, %11000110, %11111111 + .byte %11110001, %11101110, %11101110, %11101110, %11101110, %11101110, %00110001, %11111111 + .byte %10000111, %10111010, %10111010, %10111011, %10000111, %10110111, %10111010, %11111111 + .byte %00001111, %11111111, %11111111, %00011111, %11101111, %11101111, %00011111, %11111111 +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░░░░▉▉░░░░▉▉░▉░▉▉▉▉░▉░░░░░▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉░░▉▉▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉░▉░▉▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉░▉▉░▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░░░░▉▉░░░░▉▉░▉░▉▉▉░░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉▉░▉▉░▉▉░▉░▉▉▉▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉░▉▉▉▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + .byte %11100001, %11101110, %11101110, %11101110, %11100001, %11101111, %11101111, %11111111 + .byte %10000110, %10111010, %10111010, %10111010, %10000110, %10110110, %10111010, %11111111 + .byte %10111101, %10011101, %10101101, %10110101, %10111001, %10111101, %10111101, %11111111 + .byte %00000111, %11011111, %11011111, %11011111, %11011111, %11011111, %11011111, %11111111 +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░░░░▉▉░░░░▉▉░░░░▉░░░░▉░░░░░▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉▉░▉▉▉▉▉░▉▉▉▉▉▉░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉▉░▉▉▉▉▉░▉▉▉▉▉▉░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░░░▉▉▉░░░▉▉░░░▉▉▉▉░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░░░░▉▉░▉▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉░▉▉░▉▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉░▉░░░░▉░░░░▉▉░░░░▉▉▉░▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + .byte %11100001, %11101110, %11101110, %11101110, %11100001, %11101101, %11101110, %11111111 + .byte %10000110, %10111101, %10111101, %10001110, %10111111, %10111111, %10000100, %11111111 + .byte %00010000, %11110111, %11110111, %00110001, %11010111, %11010111, %00110000, %11111111 + .byte %10000011, %11101111, %11101111, %11101111, %11101111, %11101111, %11101111, %11111111 +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░░░░▉░▉▉▉░▉░▉░░░░░▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉▉░▉░▉▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░░░▉▉▉▉░▉▉▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉▉░▉░▉▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉░░░░▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ +; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + .byte %11100001, %11101111, %11101111, %11100011, %11101111, %11101111, %11100001, %11111111 + .byte %01110101, %01110101, %10101101, %11011101, %10101101, %01110101, %01110101, %11111111 + .byte %00000111, %11011111, %11011111, %11011111, %11011111, %11011111, %11011111, %11111111 +freezer_backup_lb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011011000010111011 ; ▉▉▉░░░░▉▉░▉▉░░░░▉░▉▉▉░▉▉ + MonoSpriteLine %111011101010111110110111 ; ▉▉▉░▉▉▉░▉░▉░▉▉▉▉▉░▉▉░▉▉▉ + MonoSpriteLine %111011101010111110101111 ; ▉▉▉░▉▉▉░▉░▉░▉▉▉▉▉░▉░▉▉▉▉ + MonoSpriteLine %111011101011000110011111 ; ▉▉▉░▉▉▉░▉░▉▉░░░▉▉░░▉▉▉▉▉ + MonoSpriteLine %111011101011111010101111 ; ▉▉▉░▉▉▉░▉░▉▉▉▉▉░▉░▉░▉▉▉▉ + MonoSpriteLine %111011101011111010110111 ; ▉▉▉░▉▉▉░▉░▉▉▉▉▉░▉░▉▉░▉▉▉ + MonoSpriteLine %111000011010000110111011 ; ▉▉▉░░░░▉▉░▉░░░░▉▉░▉▉▉░▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000001110011100001100 ; ▉▉▉░░░░░▉▉▉░░▉▉▉░░░░▉▉░░ + MonoSpriteLine %111110111101101101110101 ; ▉▉▉▉▉░▉▉▉▉░▉▉░▉▉░▉▉▉░▉░▉ + MonoSpriteLine %111110111011110101110101 ; ▉▉▉▉▉░▉▉▉░▉▉▉▉░▉░▉▉▉░▉░▉ + MonoSpriteLine %111110111011110101110100 ; ▉▉▉▉▉░▉▉▉░▉▉▉▉░▉░▉▉▉░▉░░ + MonoSpriteLine %111110111000000100001101 ; ▉▉▉▉▉░▉▉▉░░░░░░▉░░░░▉▉░▉ + MonoSpriteLine %111110111011110101111101 ; ▉▉▉▉▉░▉▉▉░▉▉▉▉░▉░▉▉▉▉▉░▉ + MonoSpriteLine %111110111011110101111100 ; ▉▉▉▉▉░▉▉▉░▉▉▉▉░▉░▉▉▉▉▉░░ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011110000110110000 ; ▉▉▉░░░░▉▉▉▉░░░░▉▉░▉▉░░░░ + MonoSpriteLine %111011111110111010101111 ; ▉▉▉░▉▉▉▉▉▉▉░▉▉▉░▉░▉░▉▉▉▉ + MonoSpriteLine %111011111110111010101111 ; ▉▉▉░▉▉▉▉▉▉▉░▉▉▉░▉░▉░▉▉▉▉ + MonoSpriteLine %111000111110111010110001 ; ▉▉▉░░░▉▉▉▉▉░▉▉▉░▉░▉▉░░░▉ + .byte $EF +freezer_backup_rb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %001111111111111111111111 ; ░░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011111111111111111111111 ; ░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %001111111111111111111111 ; ░░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111111111111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101101111111111111111111 ; ▉░▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101011111111111111111111 ; ▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %100111111111111111111111 ; ▉░░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte $AF +freezer_backup_lo: + MonoSpriteLine %111011111110111010111110 ; ▉▉▉░▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉▉▉░ + MonoSpriteLine %111011111110111010111110 ; ▉▉▉░▉▉▉▉▉▉▉░▉▉▉░▉░▉▉▉▉▉░ + MonoSpriteLine %111011111110000110100001 ; ▉▉▉░▉▉▉▉▉▉▉░░░░▉▉░▉░░░░▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011110000011100111 ; ▉▉▉░░░░▉▉▉▉░░░░░▉▉▉░░▉▉▉ + MonoSpriteLine %111011111111101111011011 ; ▉▉▉░▉▉▉▉▉▉▉▉▉░▉▉▉▉░▉▉░▉▉ + MonoSpriteLine %111011111111101110111101 ; ▉▉▉░▉▉▉▉▉▉▉▉▉░▉▉▉░▉▉▉▉░▉ + MonoSpriteLine %111000111111101110111101 ; ▉▉▉░░░▉▉▉▉▉▉▉░▉▉▉░▉▉▉▉░▉ + MonoSpriteLine %111011111111101110000001 ; ▉▉▉░▉▉▉▉▉▉▉▉▉░▉▉▉░░░░░░▉ + MonoSpriteLine %111011111111101110111101 ; ▉▉▉░▉▉▉▉▉▉▉▉▉░▉▉▉░▉▉▉▉░▉ + MonoSpriteLine %111011111111101110111101 ; ▉▉▉░▉▉▉▉▉▉▉▉▉░▉▉▉░▉▉▉▉░▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $00 +freezer_backup_ro: + MonoSpriteLine %101011111111111111111111 ; ▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101101111111111111111111 ; ▉░▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111111111111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000011000011111111111111 ; ░░░░▉▉░░░░▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011101011111111111111111 ; ░▉▉▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011101011111111111111111 ; ░▉▉▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011101000111111111111111 ; ░▉▉▉░▉░░░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000011011111111111111111 ; ░░░░▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011111011111111111111111 ; ░▉▉▉▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011111000011111111111111 ; ░▉▉▉▉▉░░░░▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $00 +freezer_game_lb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111100001000011000011010 ; ▉▉▉▉░░░░▉░░░░▉▉░░░░▉▉░▉░ + MonoSpriteLine %111011111011101011101011 ; ▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111011111011101011101011 ; ▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111100011011101011101011 ; ▉▉▉▉░░░▉▉░▉▉▉░▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111111101000011000011011 ; ▉▉▉▉▉▉▉░▉░░░░▉▉░░░░▉▉░▉▉ + MonoSpriteLine %111111101011111011011011 ; ▉▉▉▉▉▉▉░▉░▉▉▉▉▉░▉▉░▉▉░▉▉ + MonoSpriteLine %111000011011111011101011 ; ▉▉▉░░░░▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111100001000011000011010 ; ▉▉▉▉░░░░▉░░░░▉▉░░░░▉▉░▉░ + MonoSpriteLine %111011111011101011101011 ; ▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111011111011101011101011 ; ▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111100011011101011101011 ; ▉▉▉▉░░░▉▉░▉▉▉░▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111111101000011000011011 ; ▉▉▉▉▉▉▉░▉░░░░▉▉░░░░▉▉░▉▉ + MonoSpriteLine %111111101011111011011011 ; ▉▉▉▉▉▉▉░▉░▉▉▉▉▉░▉▉░▉▉░▉▉ + MonoSpriteLine %111000011011111011101011 ; ▉▉▉░░░░▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111011000110111011000 ; ▉▉▉▉▉▉░▉▉░░░▉▉░▉▉▉░▉▉░░░ + MonoSpriteLine %111111010111010111010111 ; ▉▉▉▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░▉▉▉ + MonoSpriteLine %111111010111010111010111 ; ▉▉▉▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░▉▉▉ + MonoSpriteLine %111111010111011010111000 ; ▉▉▉▉▉▉░▉░▉▉▉░▉▉░▉░▉▉▉░░░ + .byte $FD +freezer_game_rb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000010000111101111111111 ; ░░░░▉░░░░▉▉▉▉░▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111101111111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉░▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111101111111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉░▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110001111101111111111 ; ▉░▉▉▉░░░▉▉▉▉▉░▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111101111111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉░▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111101111111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉░▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110000111101111111111 ; ▉░▉▉▉░░░░▉▉▉▉░▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000010000111101011111111 ; ░░░░▉░░░░▉▉▉▉░▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111101011111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111101011111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110001111101011111111 ; ▉░▉▉▉░░░▉▉▉▉▉░▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111101011111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110111111101011111111 ; ▉░▉▉▉░▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %101110000111101011111111 ; ▉░▉▉▉░░░░▉▉▉▉░▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %010111110111001110000111 ; ░▉░▉▉▉▉▉░▉▉▉░░▉▉▉░░░░▉▉▉ + MonoSpriteLine %110111110110110110111011 ; ▉▉░▉▉▉▉▉░▉▉░▉▉░▉▉░▉▉▉░▉▉ + MonoSpriteLine %110111110101111010111011 ; ▉▉░▉▉▉▉▉░▉░▉▉▉▉░▉░▉▉▉░▉▉ + MonoSpriteLine %110110110101111010111011 ; ▉▉░▉▉░▉▉░▉░▉▉▉▉░▉░▉▉▉░▉▉ + .byte $55 +freezer_game_lo: + MonoSpriteLine %111111010111011101111111 ; ▉▉▉▉▉▉░▉░▉▉▉░▉▉▉░▉▉▉▉▉▉▉ + MonoSpriteLine %111111000111011101111111 ; ▉▉▉▉▉▉░░░▉▉▉░▉▉▉░▉▉▉▉▉▉▉ + MonoSpriteLine %111000111000111101110000 ; ▉▉▉░░░▉▉▉░░░▉▉▉▉░▉▉▉░░░░ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111110011101110100000110 ; ▉▉▉▉▉░░▉▉▉░▉▉▉░▉░░░░░▉▉░ + MonoSpriteLine %111101101101110111011101 ; ▉▉▉▉░▉▉░▉▉░▉▉▉░▉▉▉░▉▉▉░▉ + MonoSpriteLine %111011110101110111011101 ; ▉▉▉░▉▉▉▉░▉░▉▉▉░▉▉▉░▉▉▉░▉ + MonoSpriteLine %111011110101110111011101 ; ▉▉▉░▉▉▉▉░▉░▉▉▉░▉▉▉░▉▉▉░▉ + MonoSpriteLine %111000000101110111011101 ; ▉▉▉░░░░░░▉░▉▉▉░▉▉▉░▉▉▉░▉ + MonoSpriteLine %111011110101110111011101 ; ▉▉▉░▉▉▉▉░▉░▉▉▉░▉▉▉░▉▉▉░▉ + MonoSpriteLine %111011110110000111011110 ; ▉▉▉░▉▉▉▉░▉▉░░░░▉▉▉░▉▉▉▉░ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $FF +freezer_game_ro: + MonoSpriteLine %010101010100000010000111 ; ░▉░▉░▉░▉░▉░░░░░░▉░░░░▉▉▉ + MonoSpriteLine %010011100101111010111111 ; ░▉░░▉▉▉░░▉░▉▉▉▉░▉░▉▉▉▉▉▉ + MonoSpriteLine %110111110101111010111111 ; ▉▉░▉▉▉▉▉░▉░▉▉▉▉░▉░▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %001100001010000110000111 ; ░░▉▉░░░░▉░▉░░░░▉▉░░░░▉▉▉ + MonoSpriteLine %110101111010111010111111 ; ▉▉░▉░▉▉▉▉░▉░▉▉▉░▉░▉▉▉▉▉▉ + MonoSpriteLine %110101111010111010111111 ; ▉▉░▉░▉▉▉▉░▉░▉▉▉░▉░▉▉▉▉▉▉ + MonoSpriteLine %110100011010111010001111 ; ▉▉░▉░░░▉▉░▉░▉▉▉░▉░░░▉▉▉▉ + MonoSpriteLine %110101111010000110111111 ; ▉▉░▉░▉▉▉▉░▉░░░░▉▉░▉▉▉▉▉▉ + MonoSpriteLine %110101111010110110111111 ; ▉▉░▉░▉▉▉▉░▉░▉▉░▉▉░▉▉▉▉▉▉ + MonoSpriteLine %001101111010111010000111 ; ░░▉▉░▉▉▉▉░▉░▉▉▉░▉░░░░▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $00 +freezer_colors_lb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011110011110001101 ; ▉▉▉░░░░▉▉▉▉░░▉▉▉▉░░░▉▉░▉ + MonoSpriteLine %111011101101101101110101 ; ▉▉▉░▉▉▉░▉▉░▉▉░▉▉░▉▉▉░▉░▉ + MonoSpriteLine %111011101011110101111101 ; ▉▉▉░▉▉▉░▉░▉▉▉▉░▉░▉▉▉▉▉░▉ + MonoSpriteLine %111000011011110101111100 ; ▉▉▉░░░░▉▉░▉▉▉▉░▉░▉▉▉▉▉░░ + MonoSpriteLine %111011101000000101111101 ; ▉▉▉░▉▉▉░▉░░░░░░▉░▉▉▉▉▉░▉ + MonoSpriteLine %111011101011110101110101 ; ▉▉▉░▉▉▉░▉░▉▉▉▉░▉░▉▉▉░▉░▉ + MonoSpriteLine %111000011011110110001101 ; ▉▉▉░░░░▉▉░▉▉▉▉░▉▉░░░▉▉░▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011000110000110000 ; ▉▉▉░░░░▉▉░░░▉▉░░░░▉▉░░░░ + MonoSpriteLine %111011110111010111010111 ; ▉▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉ + MonoSpriteLine %111011110111010111010111 ; ▉▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉ + MonoSpriteLine %111000110111010111010001 ; ▉▉▉░░░▉▉░▉▉▉░▉░▉▉▉░▉░░░▉ + MonoSpriteLine %111011110111010000110111 ; ▉▉▉░▉▉▉▉░▉▉▉░▉░░░░▉▉░▉▉▉ + MonoSpriteLine %111011110111010110110111 ; ▉▉▉░▉▉▉▉░▉▉▉░▉░▉▉░▉▉░▉▉▉ + MonoSpriteLine %111011111000110111010000 ; ▉▉▉░▉▉▉▉▉░░░▉▉░▉▉▉░▉░░░░ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011100011000011000 ; ▉▉▉░░░░▉▉▉░░░▉▉░░░░▉▉░░░ + MonoSpriteLine %111011101011101011101011 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111011101011101011101011 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111000011011101011101011 ; ▉▉▉░░░░▉▉░▉▉▉░▉░▉▉▉░▉░▉▉ + .byte $EE +freezer_colors_rb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %110110001101111010000111 ; ▉▉░▉▉░░░▉▉░▉▉▉▉░▉░░░░▉▉▉ + MonoSpriteLine %101101110100111010111011 ; ▉░▉▉░▉▉▉░▉░░▉▉▉░▉░▉▉▉░▉▉ + MonoSpriteLine %011101111101011010111011 ; ░▉▉▉░▉▉▉▉▉░▉░▉▉░▉░▉▉▉░▉▉ + MonoSpriteLine %111101100101101010111011 ; ▉▉▉▉░▉▉░░▉░▉▉░▉░▉░▉▉▉░▉▉ + MonoSpriteLine %011101110101110010111011 ; ░▉▉▉░▉▉▉░▉░▉▉▉░░▉░▉▉▉░▉▉ + MonoSpriteLine %101101110101111010111011 ; ▉░▉▉░▉▉▉░▉░▉▉▉▉░▉░▉▉▉░▉▉ + MonoSpriteLine %110110001101111010000111 ; ▉▉░▉▉░░░▉▉░▉▉▉▉░▉░░░░▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %110001101111010000111111 ; ▉▉░░░▉▉░▉▉▉▉░▉░░░░▉▉▉▉▉▉ + MonoSpriteLine %101110100111010111011111 ; ▉░▉▉▉░▉░░▉▉▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %101111101011010111011111 ; ▉░▉▉▉▉▉░▉░▉▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %101100101101010111011111 ; ▉░▉▉░░▉░▉▉░▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %101110101110010111011111 ; ▉░▉▉▉░▉░▉▉▉░░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %101110101111010111011111 ; ▉░▉▉▉░▉░▉▉▉▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %110001101111010000111111 ; ▉▉░░░▉▉░▉▉▉▉░▉░░░░▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011000010000111111111111 ; ░▉▉░░░░▉░░░░▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101011110111011111111111 ; ▉░▉░▉▉▉▉░▉▉▉░▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101011110111011111111111 ; ▉░▉░▉▉▉▉░▉▉▉░▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101000110111011111111111 ; ▉░▉░░░▉▉░▉▉▉░▉▉▉▉▉▉▉▉▉▉▉ + .byte $AF +freezer_colors_lo: + MonoSpriteLine %111011101011101000011011 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░░░░▉▉░▉▉ + MonoSpriteLine %111011101011101011011011 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉░▉▉░▉▉ + MonoSpriteLine %111000011100011011101000 ; ▉▉▉░░░░▉▉▉░░░▉▉░▉▉▉░▉░░░ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $FF +freezer_colors_ro: + MonoSpriteLine %101011110000111111111111 ; ▉░▉░▉▉▉▉░░░░▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %101011110110111111111111 ; ▉░▉░▉▉▉▉░▉▉░▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011000010111011111111111 ; ░▉▉░░░░▉░▉▉▉░▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $00 +freezer_print_lb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111100001000010000010000 ; ▉▉▉▉░░░░▉░░░░▉░░░░░▉░░░░ + MonoSpriteLine %111011111011111101111101 ; ▉▉▉░▉▉▉▉▉░▉▉▉▉▉▉░▉▉▉▉▉░▉ + MonoSpriteLine %111011111011111101111101 ; ▉▉▉░▉▉▉▉▉░▉▉▉▉▉▉░▉▉▉▉▉░▉ + MonoSpriteLine %111100011000111101111101 ; ▉▉▉▉░░░▉▉░░░▉▉▉▉░▉▉▉▉▉░▉ + MonoSpriteLine %111111101011111101111101 ; ▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉░▉▉▉▉▉░▉ + MonoSpriteLine %111111101011111101111101 ; ▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉░▉▉▉▉▉░▉ + MonoSpriteLine %111000011000001101111101 ; ▉▉▉░░░░▉▉░░░░░▉▉░▉▉▉▉▉░▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111011101010000101111101 ; ▉▉▉░▉▉▉░▉░▉░░░░▉░▉▉▉▉▉░▉ + MonoSpriteLine %111011101010111101111101 ; ▉▉▉░▉▉▉░▉░▉░▉▉▉▉░▉▉▉▉▉░▉ + MonoSpriteLine %111011101010111101111101 ; ▉▉▉░▉▉▉░▉░▉░▉▉▉▉░▉▉▉▉▉░▉ + MonoSpriteLine %111011101010001101101101 ; ▉▉▉░▉▉▉░▉░▉░░░▉▉░▉▉░▉▉░▉ + MonoSpriteLine %111011101010111101010101 ; ▉▉▉░▉▉▉░▉░▉░▉▉▉▉░▉░▉░▉░▉ + MonoSpriteLine %111101011010111100111001 ; ▉▉▉▉░▉░▉▉░▉░▉▉▉▉░░▉▉▉░░▉ + MonoSpriteLine %111110111010000101111101 ; ▉▉▉▉▉░▉▉▉░▉░░░░▉░▉▉▉▉▉░▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011100001000010000 ; ▉▉▉░░░░▉▉▉░░░░▉░░░░▉░░░░ + MonoSpriteLine %111011101011111011111101 ; ▉▉▉░▉▉▉░▉░▉▉▉▉▉░▉▉▉▉▉▉░▉ + MonoSpriteLine %111011101011111011111101 ; ▉▉▉░▉▉▉░▉░▉▉▉▉▉░▉▉▉▉▉▉░▉ + MonoSpriteLine %111011101100011000111101 ; ▉▉▉░▉▉▉░▉▉░░░▉▉░░░▉▉▉▉░▉ + .byte $FF +freezer_print_rb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %010101111011000111000011 ; ░▉░▉░▉▉▉▉░▉▉░░░▉▉▉░░░░▉▉ + MonoSpriteLine %110100111010111010111111 ; ▉▉░▉░░▉▉▉░▉░▉▉▉░▉░▉▉▉▉▉▉ + MonoSpriteLine %110101011010111110111111 ; ▉▉░▉░▉░▉▉░▉░▉▉▉▉▉░▉▉▉▉▉▉ + MonoSpriteLine %110101101010110011000111 ; ▉▉░▉░▉▉░▉░▉░▉▉░░▉▉░░░▉▉▉ + MonoSpriteLine %110101110010111011111011 ; ▉▉░▉░▉▉▉░░▉░▉▉▉░▉▉▉▉▉░▉▉ + MonoSpriteLine %110101111010111011111011 ; ▉▉░▉░▉▉▉▉░▉░▉▉▉░▉▉▉▉▉░▉▉ + MonoSpriteLine %110101111011000110000111 ; ▉▉░▉░▉▉▉▉░▉▉░░░▉▉░░░░▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011111111111111111111111 ; ░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte $FF +freezer_print_lo: + MonoSpriteLine %111000011111101011111101 ; ▉▉▉░░░░▉▉▉▉▉▉░▉░▉▉▉▉▉▉░▉ + MonoSpriteLine %111011111111101011111101 ; ▉▉▉░▉▉▉▉▉▉▉▉▉░▉░▉▉▉▉▉▉░▉ + MonoSpriteLine %111011111000011000011101 ; ▉▉▉░▉▉▉▉▉░░░░▉▉░░░░▉▉▉░▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $FF +freezer_print_ro: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $00 +freezer_reset_lb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111011101010111011111111 ; ▉▉▉░▉▉▉░▉░▉░▉▉▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %111011001010111011111111 ; ▉▉▉░▉▉░░▉░▉░▉▉▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %111010111010111011111111 ; ▉▉▉░▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %111001111010111011111111 ; ▉▉▉░░▉▉▉▉░▉░▉▉▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %111010111010111011111111 ; ▉▉▉░▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %111011001010111011111111 ; ▉▉▉░▉▉░░▉░▉░▉▉▉░▉▉▉▉▉▉▉▉ + MonoSpriteLine %111011101010001000111111 ; ▉▉▉░▉▉▉░▉░▉░░░▉░░░▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000000100001000011100 ; ▉▉▉░░░░░░▉░░░░▉░░░░▉▉▉░░ + MonoSpriteLine %111111110101111011101011 ; ▉▉▉▉▉▉▉▉░▉░▉▉▉▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111111101101111011101011 ; ▉▉▉▉▉▉▉░▉▉░▉▉▉▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111111011100011011101011 ; ▉▉▉▉▉▉░▉▉▉░░░▉▉░▉▉▉░▉░▉▉ + MonoSpriteLine %111110111101111000011011 ; ▉▉▉▉▉░▉▉▉▉░▉▉▉▉░░░░▉▉░▉▉ + MonoSpriteLine %111101111101111011011011 ; ▉▉▉▉░▉▉▉▉▉░▉▉▉▉░▉▉░▉▉░▉▉ + MonoSpriteLine %111000000100001011101100 ; ▉▉▉░░░░░░▉░░░░▉░▉▉▉░▉▉░░ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111100011000011011111011 ; ▉▉▉▉░░░▉▉░░░░▉▉░▉▉▉▉▉░▉▉ + MonoSpriteLine %111011101011101001110010 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░░▉▉▉░░▉░ + MonoSpriteLine %111011111011101010101010 ; ▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉░▉░▉░▉░ + MonoSpriteLine %111011111000011011011010 ; ▉▉▉░▉▉▉▉▉░░░░▉▉░▉▉░▉▉░▉░ + .byte $EF +freezer_reset_rb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011111000010101110111111 ; ░▉▉▉▉▉░░░░▉░▉░▉▉▉░▉▉▉▉▉▉ + MonoSpriteLine %101111011110101110111111 ; ▉░▉▉▉▉░▉▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + MonoSpriteLine %101111011110101110111111 ; ▉░▉▉▉▉░▉▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + MonoSpriteLine %101111000110101110111111 ; ▉░▉▉▉▉░░░▉▉░▉░▉▉▉░▉▉▉▉▉▉ + MonoSpriteLine %101111011110101110111111 ; ▉░▉▉▉▉░▉▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + MonoSpriteLine %101111011110101110111111 ; ▉░▉▉▉▉░▉▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + MonoSpriteLine %011111001110100010001111 ; ░▉▉▉▉▉░░▉▉▉░▉░░░▉░░░▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000111110111111111111111 ; ░░░▉▉▉▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111100111111111111111 ; ▉▉▉▉▉▉▉░░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111010111111111111111 ; ▉▉▉▉▉▉░▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000110110111111111111111 ; ░░░▉▉░▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte $E8 +freezer_reset_lo: + MonoSpriteLine %111011111011101011111010 ; ▉▉▉░▉▉▉▉▉░▉▉▉░▉░▉▉▉▉▉░▉░ + MonoSpriteLine %111011101011101011111010 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉▉▉░▉░ + MonoSpriteLine %111100011000011011111011 ; ▉▉▉▉░░░▉▉░░░░▉▉░▉▉▉▉▉░▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $FF +freezer_reset_ro: + MonoSpriteLine %111010000011111111111111 ; ▉▉▉░▉░░░░░▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111011110111111111111111 ; ▉▉▉░▉▉▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000111110111111111111111 ; ░░░▉▉▉▉▉░▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $00 +freezer_exit_lb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011011101011110111 ; ▉▉▉░░░░▉▉░▉▉▉░▉░▉▉▉▉░▉▉▉ + MonoSpriteLine %111011101011101001110111 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░░▉▉▉░▉▉▉ + MonoSpriteLine %111011101011101010110111 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░▉░▉▉░▉▉▉ + MonoSpriteLine %111011101011101011010111 ; ▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉░▉░▉▉▉ + MonoSpriteLine %111000011011101011100111 ; ▉▉▉░░░░▉▉░▉▉▉░▉░▉▉▉░░▉▉▉ + MonoSpriteLine %111011011011101011110111 ; ▉▉▉░▉▉░▉▉░▉▉▉░▉░▉▉▉▉░▉▉▉ + MonoSpriteLine %111011101100001011110111 ; ▉▉▉░▉▉▉░▉▉░░░░▉░▉▉▉▉░▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111011111011000110111101 ; ▉▉▉░▉▉▉▉▉░▉▉░░░▉▉░▉▉▉▉░▉ + MonoSpriteLine %111001110010111010011101 ; ▉▉▉░░▉▉▉░░▉░▉▉▉░▉░░▉▉▉░▉ + MonoSpriteLine %111010101010111010101101 ; ▉▉▉░▉░▉░▉░▉░▉▉▉░▉░▉░▉▉░▉ + MonoSpriteLine %111011011010111010110101 ; ▉▉▉░▉▉░▉▉░▉░▉▉▉░▉░▉▉░▉░▉ + MonoSpriteLine %111011111010111010111001 ; ▉▉▉░▉▉▉▉▉░▉░▉▉▉░▉░▉▉▉░░▉ + MonoSpriteLine %111011111010111010111101 ; ▉▉▉░▉▉▉▉▉░▉░▉▉▉░▉░▉▉▉▉░▉ + MonoSpriteLine %111011111011000110111101 ; ▉▉▉░▉▉▉▉▉░▉▉░░░▉▉░▉▉▉▉░▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111000011000011000010111 ; ▉▉▉░░░░▉▉░░░░▉▉░░░░▉░▉▉▉ + MonoSpriteLine %111011101011110111110110 ; ▉▉▉░▉▉▉░▉░▉▉▉▉░▉▉▉▉▉░▉▉░ + MonoSpriteLine %111011101011110111110101 ; ▉▉▉░▉▉▉░▉░▉▉▉▉░▉▉▉▉▉░▉░▉ + MonoSpriteLine %111011101000111000110011 ; ▉▉▉░▉▉▉░▉░░░▉▉▉░░░▉▉░░▉▉ + .byte $EE +freezer_exit_rb: + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %010000011000110000111111 ; ░▉░░░░░▉▉░░░▉▉░░░░▉▉▉▉▉▉ + MonoSpriteLine %011101110111010111011111 ; ░▉▉▉░▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %011101110111010111011111 ; ░▉▉▉░▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %011101110111010111011111 ; ░▉▉▉░▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %011101110111010000111111 ; ░▉▉▉░▉▉▉░▉▉▉░▉░░░░▉▉▉▉▉▉ + MonoSpriteLine %011101110111010110111111 ; ░▉▉▉░▉▉▉░▉▉▉░▉░▉▉░▉▉▉▉▉▉ + MonoSpriteLine %011101111000110111011111 ; ░▉▉▉░▉▉▉▉░░░▉▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %010000011000110000111111 ; ░▉░░░░░▉▉░░░▉▉░░░░▉▉▉▉▉▉ + MonoSpriteLine %111101110111010111011111 ; ▉▉▉▉░▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %111101110111010111011111 ; ▉▉▉▉░▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ + MonoSpriteLine %111101110111010111011111 ; ▉▉▉▉░▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉ + .byte $F7 +freezer_exit_lo: + MonoSpriteLine %111011101011111111010101 ; ▉▉▉░▉▉▉░▉░▉▉▉▉▉▉▉▉░▉░▉░▉ + MonoSpriteLine %111011101011111111010110 ; ▉▉▉░▉▉▉░▉░▉▉▉▉▉▉▉▉░▉░▉▉░ + MonoSpriteLine %111000011000010000110111 ; ▉▉▉░░░░▉▉░░░░▉░░░░▉▉░▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $FF +freezer_exit_ro: + MonoSpriteLine %111101110111010000111111 ; ▉▉▉▉░▉▉▉░▉▉▉░▉░░░░▉▉▉▉▉▉ + MonoSpriteLine %111101110111010111111111 ; ▉▉▉▉░▉▉▉░▉▉▉░▉░▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %011101111000110111111111 ; ░▉▉▉░▉▉▉▉░░░▉▉░▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %111111111111111111111111 ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + MonoSpriteLine %000000000000000000000000 ; ░░░░░░░░░░░░░░░░░░░░░░░░ + .byte $00 +freezer_action2: + lda $02 + bmi :+ + jmp freezer_action3 +: jmp freezer_loop + + +.segment "view_graphics" + .byte 5, 6, 7, 8, 9, 10, 11, 12 + .byte 13, 14, 15, 5, 16, 17, 18, 19 + .byte 20, 5, 16, 17, 18, 21, 28, 5 + .byte 16, 17, 18, 22, 28, 5, 16, 17 + .byte 18, 23, 28, 24, 25, 26, 28, 28 + ; ▉▉░░░░▉▉▉░░░▉▉░░░░▉▉░░░░▉▉░░░░▉░░░░▉▉▉▉▉ + ; ▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░▉▉▉▉░▉▉▉░▉▉▉▉ + ; ▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░▉▉▉▉░▉▉▉░▉▉▉▉ + ; ▉▉░░░░▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉░░░▉▉ ▉▉▉░▉▉▉▉ + ; ▉▉░▉▉▉░▉░▉▉▉░▉░░░░▉▉░▉▉▉░▉░▉▉▉▉░░░░▉▉▉▉▉ + ; ▉▉░▉▉▉░▉░▉▉▉░▉░▉▉░▉▉░▉▉▉░▉░▉▉▉▉░▉▉░▉▉▉▉▉ + ; ▉▉░░░░▉▉▉░░░▉▉░▉▉▉░▉░░░░▉▉░░░░▉░▉▉▉░▉▉▉▉ + ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %11000011, %11011101, %11011101, %11000011, %11011101, %11011101, %11000011, %11111111 + .byte %10001100, %01110101, %01110101, %01110101, %01110100, %01110101, %10001101, %11111111 + .byte %00110000, %11010111, %11010111, %11010111, %00110111, %10110111, %11010000, %11111111 + .byte %11000010, %01011110, %01011110, %01000110, %01011110, %01011110, %11000010, %11111111 + .byte %00011111, %11101111, %11101111, %11101111, %00011111, %11011111, %11101111, %11111111 + ; ▉▉░░░░▉▉░░░▉▉░░░░▉▉░░░░▉▉░░░▉▉░▉▉▉▉░▉░░░░▉▉▉▉▉▉▉ + ; ▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉▉░▉▉▉░▉░░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉▉░▉▉▉▉▉░▉░▉▉░▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░░░▉▉░▉▉▉░▉░▉▉▉░▉░░░▉▉░▉▉░░▉░▉▉░▉░▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░▉▉▉▉░▉▉▉░▉░░░░▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░░▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░▉▉▉▉░▉▉▉░▉░▉▉░▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░▉▉▉▉▉░░░▉▉░▉▉▉░▉░░░░▉▉░░░▉▉░▉▉▉▉░▉░░░░▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %11000011, %11011110, %11011110, %11000110, %11011110, %11011110, %11011111, %11111111 + .byte %00011000, %11101011, %11101011, %11101011, %11101000, %11101011, %00011011, %11111111 + .byte %01100001, %10101111, %10101111, %10100011, %01101111, %01101111, %10100001, %11111111 + .byte %10001101, %01110100, %01111101, %01100101, %01110101, %01110101, %10001101, %11111111 + .byte %11101000, %11101011, %01101011, %10101011, %11001011, %11101011, %11101000, %11111111 + .byte %01111111, %10111111, %10111111, %10111111, %10111111, %10111111, %01111111, %11111111 + ; ▉░░░▉▉▉░░░▉▉░▉▉▉▉░░░▉▉░░░░▉▉▉░░░▉▉▉▉▉▉▉▉ + ; ░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉▉ + ; ░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉▉░▉░▉▉░░▉▉▉▉▉▉▉ + ; ░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉▉░▉░▉░▉░▉▉▉▉▉▉▉ + ; ░▉▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░░░░▉▉░░▉▉░▉▉▉▉▉▉▉ + ; ░▉▉▉░▉░▉▉▉░▉░▉▉▉░▉▉▉░▉░▉▉░▉▉░▉▉▉░▉▉▉▉▉▉▉ + ; ▉░░░▉▉▉░░░▉▉░░░▉▉░░░▉▉░▉▉▉░▉▉░░░▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %10001110, %01110101, %01111101, %01111101, %01111101, %01110101, %10001110, %11111111 + .byte %00110111, %11010111, %11010111, %11010111, %11010111, %11010111, %00110001, %11111111 + .byte %10001100, %01110101, %01110101, %01110101, %01110100, %01110101, %10001101, %11111111 + .byte %00111000, %11010111, %11010110, %11010101, %00110011, %10110111, %11011000, %11111111 + .byte %11111111, %01111111, %01111111, %01111111, %01111111, %01111111, %11111111, %11111111 + ; ░░▉▉▉▉░▉ + ; ▉▉░▉▉░░▉ + ; ▉▉░▉▉▉░▉ + ; ▉▉░▉▉▉░▉ + ; ░░▉▉▉▉░▉ + ; ▉░▉▉▉▉░▉ + ; ▉▉░▉▉░░░ + ; ▉▉▉▉▉▉▉▉ + .byte %00111101, %11011001, %11011101, %11011101, %00111101, %10111101, %11011000, %11111111 + ; ░░▉▉▉░░▉ + ; ▉▉░▉░▉▉░ + ; ▉▉░▉▉▉▉░ + ; ▉▉░▉▉▉░▉ + ; ░░▉▉▉░▉▉ + ; ▉░▉▉░▉▉▉ + ; ▉▉░▉░░░░ + ; ▉▉▉▉▉▉▉▉ + .byte %00111001, %11010110, %11011110, %11011101, %00111011, %10110111, %11010000, %11111111 + ; ░░▉▉░░░░ + ; ▉▉░▉▉▉▉░ + ; ▉▉░▉▉▉▉░ + ; ▉▉░▉▉░░▉ + ; ░░▉▉▉▉▉░ + ; ▉░▉▉▉▉▉░ + ; ▉▉░▉░░░▉ + ; ▉▉▉▉▉▉▉▉ + .byte %00110000, %11011110, %11011110, %11011001, %00111110, %10111110, %11010001, %11111111 + ; ▉▉░░░░▉░▉▉▉░▉░▉░░░░░▉▉▉▉ + ; ▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░▉▉▉▉▉░▉░▉▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░░░▉▉▉▉░▉▉▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░▉▉▉▉▉░▉░▉▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░▉▉▉▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉░░░░▉░▉▉▉░▉░▉▉▉░▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ + .byte %11000010, %11011110, %11011111, %11000111, %11011111, %11011110, %11000010, %11111111 + .byte %11101010, %11101011, %01011011, %10111011, %01011011, %11101011, %11101011, %11111111 + .byte %00001111, %10111111, %10111111, %10111111, %10111111, %10111111, %10111111, %11111111 + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111 + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ▉▉▉▉▉▉▉▉ + ; ░▉▉▉▉▉▉▉ + .byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %01111111 + +.segment "freezer_menu" + +; $F900 +freezer_exec_menu: + sei + ldx #$00 ; Initialize DDR to make sure we can read keyboard + stx $DC03 ; DDR B + dex + stx $DC02 ; DDR A + stx $05 + lda #$80 + sta $DC0E ; Initialize timer A + sta $DC0F ; Initialize timer B + lda #$7B ; Switch the VIC-II to illegal bitmap mode 1 + sta $D011 ; VIC control register + lda $DD00 + and #$FC ; Switch the VIC-II to bank 3 + sta $DD00 + ; We want a raster interrupt on scanline 1 + lda #$01 + sta $D012 + sta $D01A + sta $D019 + lda #$FF + sta $02 + jsr colram_topline_green + ; Screen RAM at $F000, charset at $F000 + lda #$CC + sta $D018 ; VIC memory control register + ; Black background + lda #$00 + sta $D021 + ; Delay loop + ldy #$00 +: dey + bne :- +WF942: + jsr colram_topline_green + ldy $03 ; Currently selected pull-down menu + ; Under normal circumstances we initiallize $03 (currently selected menu) + ; with zero (backup menu), but in case we return from PRINT/VIEW $03 + ; already contains #$03 (print menu), so we leave it as it is. + cpy #$03 ; Print menu? + beq WF951 + ldy #$00 + sty $03 +menu_changed: + ldy $03 +WF951: + jsr show_selected_menu + lda #$00 + sta $D418 ; Set volume to 0 to create a pop on the speakers + cli +freezer_loop: + lda #$FF + sta $DC00 ; Deselect all keyboard lines + ldx #$10 +: lda $DC01 ; Read gamee port 2 + cmp #$FF + bne :+ ; Joystick action? Then jump + dex + bne :- + lda $DC00 ; Data port A #1: keyboard, joystick, paddle, optical pencil + cmp #$FF + bne :+ + jmp keyaction +: cmp $04 ; Joystick changed? + beq freezer_loop + jsr joyaction + bcc jmp_freezer_action ; Button pressed? Then jump + txa + beq :+ + bpl leftright + jmp left +: tya + beq :+ + bpl updown + jmp up +: jmp freezer_loop + +keyaction: + lda #$FE ; Select keyboard column H + sta $DC00 +: lda $DC01 + cmp $DC01 ; Wait for keyboard change + bne :- + cmp $04 ; Changeed to previous value? + beq freezer_loop + sta $04 + cmp #$F7 ; F7 pressed? + beq jmp_freezer_action + ldx #$BF ; Select keyboard column B + stx $DC00 + ldx $DC01 + cmp #$7F ; CRSR UP/DOWN presset? + beq updown + cmp #$FB ; CRSR LEFT/RIGHT presset? + beq leftright + jmp freezer_loop +jmp_left: + jmp left + +jmp_freezer_action: + jmp freezer_action1 + +updown: + cpx #$EF ; Right shift prsseed? + beq jmp_up + jmp down + +leftright: + cpx #$EF ; Left shift pressed? + beq jmp_left + jmp right + +jmp_up: + jmp up + + +;F9D2 +; +; In/out +; y = Current menu +; x = Current item in menu +; +joyaction_16k = joyaction & $BFFF +joychanged_16k = joychanged & $BFFF + +joyaction: + lda $DC00 ; Data port A #1: keyboard, joystick, paddle, optical pencil + cmp $04 ; Jump Vector: real-integer conversion + bne joychanged + lda $DC01 ; Data port B #1: keyboard, joystick, paddle + cmp $04 ; Jump Vector: real-integer conversion + bne joychanged + ldx #$00 + ldy #$00 + sec + rts +joychanged: + sta $04 + ldy #$00 + ldx #$00 + lsr ; C = UP (0=active) + bcs :+ + dey +: lsr ; C = Down (0=active) + bcs :+ + iny +: lsr ; C = Left (0=active) + bcs :+ + dex +: lsr ; C = Right (0=active) + bcs :+ + inx +: lsr ; C = Fire button (0=press) + rts + +right: + ldy $03 + lda #$FF + sta $02 + lda #$0F + sta $D418 ; Select volume and filter mode + iny + sty $03 + cpy #$06 + bne jmp_menu_changed +WFA10: + ldx #$FF + stx $02 + jmp WF942 + +down: + ldy $03 + inc $02 +WFA1B: + lda $02 + ldx #$0F + stx $D418 ; Select volume and filter mode + cmp #$04 + bcc WFA32 +WFA26: + ldx #$FF + stx $02 + jsr colram_topline_green + lda #$00 + sta $D015 ; Sprites Abilitator +WFA32: + cpy #$02 + bcc WFA3A + cmp #$03 + bcs WFA26 +WFA3A: + jsr colram_topline_green +jmp_menu_changed: + jmp menu_changed + +up: + dec $02 + bmi WFA3A + ldy $03 + jmp WFA1B + +WFA49: + lda $02 + sta $05 + inc $03 + lda #$01 + sta $02 + jmp WF951 + + ; + ; User has selected an option in the freezer menu with fire button or F7. + ; + ; Looks like some code had to be patched into binary code that did + ; already exist here. +freezer_action1: + jmp freezer_action2 + nop +freezer_action3: + ldy $03 ; Currently open menu + cpy #$02 + beq WFA49 + lda menu_action_offset,y + ; An overcomplicated way to compute A:=A+$02 : + tay + ldx $02 +: iny + dex + bpl :- + tya + jmp freezer_complete_action + +;$FA6E +left: + dec $03 + beq WFA10 + bmi WFA10 + dec $03 ; Right will increase it again + jsr colram_topline_green + jmp right + +show_selected_menu: + lda #$0F + sta $D418 ; Set volume to max to cause speaker pop + lda #$C8 ; Screen is 40 columns wide + sta $D016 + sei + jsr _freezer_upd_sprptr_16k ; Sprite pointers are in RAM, 16K mode is needed + cli + lda #$00 + sta $D01B ; Sprite-background screen priority + sta $D01D ; (2X) horizontal expansion (X) sprite 0..7 + sta $D01C ; Set multicolor mode for sprite 0..7 + sta $D017 ; (2X) vertical expansion (Y) sprite 0..7 + ldy $03 ; Currently selected drop-down menu + cpy #$04 + bcc :+ + lda #$28 ; Reset menu has right sprites on xpos>255 + cpy #$05 + bcc :+ + lda #$3C ; Exit menu has all sprites on xpos>255 +: sta $D010 ; Position X MSB sprites 0..7 + lda freezer_menus_xpositions,y + sta $D004 ; Position X sprite 2 + sta $D008 ; Position X sprite 4 + clc + adc #24 ; Sprite is 24 px wide, next one 24px to the right + sta $D006 ; Position X sprite 3 + sta $D00A ; Position X sprite 5 + lda #58 ; Y position of top sprites of menu + sta $D005 ; Position Y sprite 2 + sta $D007 ; Position Y sprite 3 + lda #79 ; Bottom sprites 21 px below top sprites + sta $D009 ; Position Y sprite 4 + sta $D00B ; Position Y sprite 5 + ldx $02 + bpl :+ + jsr highlight_selected_menu +: lda #$3C + sta $D015 ; Sprites Abilitator + rts + +freezer_menus_xpositions: + .byte $18, $50, $80, $B8, $E8, $18 +selected_item_rasterlines: + .byte $39, $41, $49, $51 +menu_horz_pos: + .byte $01, $08, $0E, $15, $1B, $21, $27 +unknown1: + .byte $01, $06, $0C, $12, $18 +WFAEF: + .byte $1E, $24, $29 +menu_action_offset: + .byte $00, $04, $08, $0B, $0E, $11 +selected_item_wait_iters: + .byte $1E, $16, $16, $13 +selected_item_endwait: + .byte $13, $12, $10, $10 + + +freezer_irq_handler: + sei + pha + txa + pha + tya + pha + lda #$CC + sta $D018 ; VIC memory control register + lda #$1B ; text mode, 25 lines, yscroll=3 + sta $D011 ; VIC control register +: lda $D012 ; Reading/Writing IRQ balance value + cmp #$39 + bcc :- + cpx $01 ; Wait some cyles + ldx #$09 +: dex + bne :- + ldx #$1C + stx $D018 ; VIC memory control register + ldx #$0A +: dex + bne :- + nop + lda #$7B ; invalid bitmap mode 1, 25 lines, yscroll=3 + sta $D011 ; VIC control register + nop + nop + ldx $02 ; selected item + bmi WFB67 + beq WFB44 +: lda $D012 ; Reading/Writing IRQ balance value + cmp selected_item_rasterlines,x + bcc :- + ldy selected_item_wait_iters,x +: dey + bne :- +WFB44: + nop + lda #$01 ; white + sta $D029 ; Color sprite 2 + sta $D02A ; Color sprite 3 + sta $D02B ; Color sprite 4 + sta $D02C ; Color sprite 5 + lda selected_item_rasterlines,x + clc + adc #$07 +WFB59: + cmp $D012 ; Reading/Writing IRQ balance value + bcc WFB61 + jmp WFB59 + +WFB61: + ldy selected_item_endwait,x +: dey + bne :- +WFB67: + ldx #$0D ; light green + stx $D029 ; Color sprite 2 + stx $D02A ; Color sprite 3 + stx $D02B ; Color sprite 4 + stx $D02C ; Color sprite 5 + lda #$01 ; next raster irq at raster line 1 + sta $D012 ; Reading/Writing IRQ balance value +: lda $D012 ; wait until raster line 96 + cmp #$60 + bcc :- + lda #$01 + sta $D019 ; Interrupt indicator register + pla + tay + pla + tax + pla + rti + +; +; Make set the first line of the colour RAM to light_green +; +; $FB8C +colram_topline_green_16k = colram_topline_green & $BFFF +colram_topline_green: + ldx #40-1 +: lda #13 ; Light-green + sta $D800,x ; Color RAM + dex + bpl :- + inx + rts + +; $FB98 +highlight_selected_menu: + jsr colram_topline_green + ldy $03 + clc + lda menu_horz_pos,y + tax + sbc menu_horz_pos+1,y + eor #$FF + tay + cpy #$07 + bcc :+ + dey +: lda #1 ; White +: sta $D7FF,x + inx + dey + bne :- + rts + +;$FBB7 +freezer_complete_action: + sei + pha + ldy #$A0 + ldx #$00 +: dex + bne :- + dey + bne :- +: lda $DC01 ; Data port B #1: keyboard, joystick, paddle + cmp $04 + beq :- +: lda $DC00 ; Data port A #1: keyboard, joystick, paddle, optical pencil + cmp $04 + beq :- + pla + cmp #$0D + bne :+ + ; Disable all sprites + lda #$00 + sta $D015 ; Sprites Abilitator + jmp _show_view_menu +: ldx #$00 + stx $D01A ; IRQ mask register + rts + +; +; Draw the menu during raster interrupt +; +WFBE4: + ; Screen RAM and charset at $F800 + ldx #$EE + stx $D018 ; VIC memory control register + ; Wait until raster line 58 (first visible line is 51) +: lda $D012 + cmp #57 + bcc :- + ; Wait some cycles + nop + ldx #$09 +: dex + bne :- + ; Scroll down 1 line + lda #$1C + sta $D011 ; VIC control register + ; Wait some cycles + ldx #$0A +: dex + bne :- + ; Illegal bitmap mode 1, keep the scroll down + lda #$7C + sta $D011 ; VIC control register + rts + +.segment "freezer_menu_16k" + +; $BC40 +freezer_update_spritepointers: + ldy $03 + ldx freezer_spritepointers_base,y + stx $C7FA + inx + stx $C7FB + inx + stx $C7FC + inx + stx $C7FD + rts + +freezer_spritepointers_base: + .byte $C5, $C9, $CD, $D1, $D5, $D9 + +; $BC5B +show_view_menu: + sei + lda $0314 + pha + lda $0315 + pha + lda #view_irq_handler2 + sta $0315 ; Vector: Hardware Interrupt (IRQ) + lda viciireg_backup + $01 ; $D011 backup + pha + ora #$03 ; Reset screen scroll? + and #$7B + sta viciireg_backup + $01 + ldx #4 +: lda $AC,x + sta $D020,x ; Border color + dex + bpl :- + jsr colram_topline_green_16k + lda $05 + bmi @1 + cmp #$01 + beq :+ + eor #$02 +: sta $03 + lda #$FF + sta $05 + jmp @2 +@1: inc $05 + ldy #$0D + sty $03 + jsr ultimax_highlight_selected_menu + ldy #$06 + sty $03 + ; Interrupt on raster line 2 +@2: lda #$02 + sta $D012 ; Reading/Writing IRQ balance value + lda #$3F + sta $02 + jsr restore_sprites + ; Enable raster interrupt + lda #$01 + sta $D019 + sta $D01A +: cli + jmp :- ; Infinite loop! + +WBCBC: + sei + ; Background black + lda #$00 + sta $D021 + ; 25 line mode + lda #$C8 + sta $D016 + ; Set VIC-II to bank 3 + lda $DD00 + and #$FC + sta $DD00 + jsr ultimax_fbe4 +;WBCD2 +show_frozen_screen: + ; Restore VIC-II bank + lda ciareg_backup + $10 ; $DD00 backup + sta $DD00 + lda viciireg_backup + $08 ; $D018 backup + sta $D018 ; VIC memory control register + lda viciireg_backup + $11 ; $D021 backup + sta $D021 ; Background 0 color + lda viciireg_backup + $06 ; $D016 backup + sta $D016 ; VIC control register + nop + nop + inc viciireg_backup + $01 ; $D011 backup, scroll 1 line down + lda viciireg_backup + $01 + sta $D011 ; VIC control register + dec viciireg_backup + $01 ; scroll back up + lda $02 + cmp #$F0 ; VIC-II line 240? + bcc :+ + ; Show original sprites + lda viciireg_backup + $05 ; $D015 backup + sta $D015 ; Sprites Abilitator +: rts + +; +; This raster interrupt runs in 16K mode and thus has to use +; the vector at $0314. +; + +view_irq_handler2: + sei ; Unnecessary, interrupts are already + ; disabled by the CPU. + lda $D012 + cmp #$01 ; Raster line 1? + beq rline1 ; Then jump +WBD05: + lda $D011 + ora #$60 ; Invalid bitmap mode 1 + screen disabled + sta $D011 + lda #$00 + sta $D015 ; Disable sprites + lda $05 + bpl :+ + jmp WBD98 +: beq :+ + dec $05 +: lda #$FF ; Deselect the keyboard + sta $DC00 + ldx #$20 +: dex + lda $DC01 ; Read joystick 2 + cmp #$FF + bne :+ ; No activity? Then jump. + dex + bne :- ; Next attempt to read joystick. + beq stickinactive ; No joystick +: jsr joychanged_16k + jmp WBD3F +WBD37: + lda #$FF ; Deselect the keyboard + sta $DC00 + jsr joyaction_16k +WBD3F: + lda $05 + bne WBD55 + bcc WBD98 ; Firebutton pressed + txa ; Left/right status + beq WBD55 ; No change + bmi view_left ; Left + jmp view_right ; Right + +rline1: + ; Switch to normal text mode to display menu bar + lda #$1B + sta $D011 + jmp WBE22 + +WBD55: + tya ; Up/down status + beq WFD5D ; No change + bmi view_up ; Up + jmp view_down ; Down + +WFD5D: + jmp WBE0A + +view_left: + dec $03 ; Decrease selected menu + bpl WFDB4 + inc $03 ; Can't go left of leftmost menu + beq WFDB4 +view_right: + cpx #$EF + beq view_left + lda $03 + cmp #$06 + bcs WFDEC + inc $03 + bne WBDF0 +stickinactive: + lda #$FE ; Select keyboard column H + sta $DC00 + lda $DC01 + ldx #$BF ; Select keyboard column B + stx $DC00 + ldx $DC01 + cmp #$7F ; CRSR UP/DN + beq view_down + ldy $05 + bne WBD37 + cmp #$FB ; CRSR L/R + beq view_right + cmp #$F7 ; F7 + bne WBD37 + sta $04 +WBD98: + inc $05 + ldx $03 + beq WFDAF + cpx #$06 + beq WFDBD +WFDA2: + cpx #$02 + bne :+ + lda $9D + and #$20 + bne WFDB7 +: dex + beq WFDC0 +WFDAF: + inc $D020,x ; Border color + inc $AC,x +WFDB4: + jmp WBDF0 + +WFDB7: + lda $03 + pha + jmp WBE65 + +WFDBD: + jmp exit_infinite_loop + +WFDC0: + lda $03 + pha + jmp WBE69 + +view_down: + cpx #$EF ; Right shift? + beq view_up + lda #$50 + sta $04 + inc $02 ; Increase current y position + lda $02 + cmp #$F8 ; Don't go beyond line 248 + bcs WFE1F + bne WBE0A +view_up: + ; Disable all sprites: + lda #$00 + sta $D015 + dec $02 ; Decrease current y position + inc $04 + lda $02 + cmp #$3E ; Top reached? (line 62) + beq exit_infinite_loop ; Then exit + bcs WBE0A + jmp WBE0A + +WFDEC: + lda #$00 + sta $03 +WBDF0: + lda #$0F + sta $D418 ; Select volume and filter mode + lda #$0B + sta $05 + jsr colram_topline_green_16k + lda $03 + pha + clc + adc #$07 + sta $03 + jsr ultimax_highlight_selected_menu + pla + sta $03 +WBE0A: + lda #$01 ; Next raster interrupt on scanline 1 + sta $D012 ; Reading/Writing IRQ balance value +WBE0F: + lda #$01 + sta $D019 ; Interrupt indicator register + sta $D01A ; IRQ mask register + lda #$00 + sta $D418 ; Select volume and filter mode + jmp $EA7E ; Pull registers from stack and RTI + +WFE1F: + jmp WBF39 + +; BE22 +WBE22: + ; Disable all sprites + lda #$00 + sta $D015 + jsr WBCBC + lda $02 + pha + and #$0F + cmp #$04 + beq :+ + cmp #$0C + beq :+ + pla + sta $D012 ; Next raster interrupt at end of visible area + jmp WBE0F +: pla +: cmp $D012 ; Reading/Writing IRQ balance value + bne :- + nop + nop + jmp WBD05 + +; +; Exits the inifite loop at the end of show_view_menu +; +exit_infinite_loop: + ldy #$03 + sty $03 + tsx + inx + inx + inx + inx + inx + inx + txs + pla + sta viciireg_backup + $01 + pla + sta $0315 + pla + sta $0314 + rts + +vicii_bank_base: + .byte $c0,$80,$40,$00 + +WBE65: + lda #$FE + sta $03 +WBE69: + lda $06 + pha + lda viciireg_backup + $01 + and #$20 ; Bitmap mode? + beq inc_colour_ram ; Jump if text mode + lda #$00 + sta $04 + lda $D018 + and #$F0 + lsr + lsr + sta $05 + lda ciareg_backup + $10 ; $DD00 backup + and #$03 ; Get VIC-II bank + tax + lda vicii_bank_base,x + clc + adc $05 + sta $05 + ldy #$00 + ldx #$04 +@1: lda ($04),y + pha + sei ; Not necessary? + lda $03 + cmp #$FE + bne :+ + pla + pha + and #$F0 + sta $06 + pla + and #$0F + adc #$01 + ora $06 + jmp @2 +: pla + pha + and #$0F + sta $06 + pla + clc + and #$F0 + adc #$10 + ora $06 + ; Screen is 1000 bytes, $3E8, so stop when X=1 and Y=$E8 +@2: cpx #$01 + bne :+ + cpy #$E8 + beq exit_colour +: sta ($04),y + iny + bne @1 + inc $05 + dex + bne @1 + jmp exit_colour + +; +; Adjust the foreground colour by increasing all values in colour ram +; +inc_colour_ram: + ldx #$00 +: inc $D800,x ; Color RAM + inc $D900,x ; Color RAM + inc $DA00,x ; Color RAM + inc $DB00,x ; Color RAM + dex + bne :- + ldx #$0F +: inc colram_backup,x + dex + bpl :- +exit_colour: + jsr colram_topline_green_16k + pla + sta $06 + pla + sta $03 + cli + jmp WBDF0 + +;$BEF2 +restore_sprites: + sei + ldx #$07 +: lda spritexy_backup,x + sta $D004,x + dex + bpl :- + lda viciireg_backup + $00 + sta $D010 ; Position X MSB sprites 0..7 + lda viciireg_backup + $07 + sta $D017 ; (2X) vertical expansion (Y) sprite 0..7 + ldx #$03 +: lda viciireg_backup + $0A,x + sta $D01A,x + lda viciireg_backup + $19,x + sta $D029,x + dex + bpl :- + lda viciireg_backup + $15 + sta $D025 ; Multicolor animation 0 register + lda viciireg_backup + $16 + sta $D026 ; Multicolor animation 1 register + rts + +;$BF21 + ; + ; Dead code??? + ; + jsr show_frozen_screen + ldx #23 +: lda $DBE8,x ; Color RAM + sta $D800,x ; Color RAM + dex + bpl :- + ldx #15 +: lda colram_backup,x + sta $D818,x ; Color RAM + dex + bpl :- +WBF39: + lda #$F8 + sta $02 + jmp WBE0A + + jmp $2000 + + +.segment "freezer" +freezer_nmi_handler: + sei + pha + lda $00 + pha + lda #$2F + sta $00 ; default value of processor port DDR + lda $01 ; save cpu port + ora #$20 ; cassette motor off - but don't store + pha + lda #$37 ; init cpu port + sta $01 ; 6510 I/O register + + ; Activate Ultimax mode and bank 3, NMI line stays active + lda #fcio_bank_3|fcio_c64_ultimaxmode + sta fcio_reg ; NMI = 1, GAME = 1, EXROM = 0 + lda $DC0B ; Day time clock #1: Hour+[indicator AM/PM] + lda $DD0B ; Day time clock #2: Hour+[indicator AM/PM] + txa + pha + tya + pha + lda $02A1 + pha + ldx #10 +: lda $02,x + pha + dex + bpl :- + lda $DD0E ; Control register A of CIA #2 + pha + lda $DD0F ; Control register B of CIA #2 + pha + lda #$00 + sta $DD0E ; Control register A of CIA #2 + sta $DD0F ; Control register B of CIA #2 + lda #$7C ; Stored into $DD0D + ldx #fcio_bank_3|fcio_c64_16kcrtmode ; Stored info $FFFF + jmp t_freezer_init + +.segment "freezer_vectors" + .addr freezer_nmi_handler, freezer_nmi_handler, freezer_irq_handler diff --git a/bank3/freezer_reset.s b/bank3/freezer_reset.s new file mode 100644 index 0000000..d2cf922 --- /dev/null +++ b/bank3/freezer_reset.s @@ -0,0 +1,108 @@ +;***************************************************************************** +; Final Cartridge III reconstructed source code +; +; This file implements the functions of the reset menu of the freezer +;***************************************************************************** + + .setcpu "6502x" + +.include "../core/kernal.i" +.include "../core/fc3ioreg.i" +.include "persistent.i" + +.import _jmp_bank,_enable_fcbank0,_disable_fc3rom_set_01 +.importzp __FREEZERZP_START__,__FREEZERZP_SIZE__ +.import __freezer_restore_1_LOAD__,__freezer_restore_1_SIZE__ +.import __freezer_restore_2_RUN__,__freezer_restore_2_SIZE__ +.importzp freezer_mem_a,freezer_mem_a_val,freezer_mem_b,freezer_mem_b_val +.import monitor +.import freezer_screenshot_prepare + +.segment "freezer_monitor" + +init_load_and_basic_vectors = $8021 + +.global freezer_goto_monitor +freezer_goto_monitor: + ldx #$FF + txs + jsr IOINIT_direct + jsr RESTOR_direct + lda #$00 + tay +: sta $0002,y ; Clear zeropage + sta $0200,y ; Clear $02xx + iny + bne :- + ldx #<$A000 + ldy #>$A000 + jsr $FD8D ; Set top, bottom of memory and screen base + jsr CINT_direct + jsr $E453 ; Routine: Set BASIC vectors (case 0x300..case 0x309) + jsr $E3BF ; Routine: Set USR instruction and memory for BASIC + lda #>(monitor-1) + pha + lda #<(monitor-1) + pha + lda #>(init_load_and_basic_vectors-1) + pha + lda #<(init_load_and_basic_vectors-1) + pha + jmp _enable_fcbank0 + + +.segment "freezer_reset" + +.global freezer_zero_fill +freezer_zero_fill: + ldy #$00 + sty $AC + lda #$08 + sta $AD + lda #$33 + sei + sta $01 + tya +: sta ($AC),y + iny + bne :- + inc $AD + bne :- +c64_reset: + lda #>(START-1) + pha + lda #<(START-1) + pha + lda #$37 + sta $01 + jmp _enable_fcbank0 + +.global write_mg87_and_reset +write_mg87_and_reset: + ldx #sizeof_MG87 - 1 +: lda MG87,x + sta $CFFC,x + dex + bpl :- + bmi c64_reset ; always + +MG87: .byte "MG87" +sizeof_MG87 = .sizeof(MG87) + + ; + ; Got to the printer settings menu + ; +.global freezer_goto_settings +freezer_goto_settings: + ldy #__FREEZERZP_SIZE__ - 1 + lda freezer_mem_a_val +: sta (freezer_mem_a),y + dey + bpl :- + ldy #<__freezer_restore_1_SIZE__ - 1 + lda freezer_mem_b_val +: sta (freezer_mem_b),y + dey + bpl :- + jmp freezer_screenshot_prepare ; $A000 + diff --git a/bank3/mysterycode.s b/bank3/mysterycode.s new file mode 100644 index 0000000..9932828 --- /dev/null +++ b/bank3/mysterycode.s @@ -0,0 +1,1718 @@ +;**************************** +; This code is not fully understood yet +; +; Its purpose seems to be reading and writing the directory. +;**************************** + + .setcpu "6502x" + +.include "../core/kernal.i" +.include "../core/fc3ioreg.i" +.include "persistent.i" + +.import store_a_ff_to_ae,fill_loop +.import __diredit_cmds_LOAD__,__diredit_cmds_RUN__,__diredit_cmds_SIZE__ +.import W9200 +.import not_last_sector +.import next_dir_entry + +.segment "mysterycode" + + .byte $b0,$90,$da +W915D: + jsr next_dir_entry+1 ; ??????!! + lda #$80 + sta $90 ; Statusbyte ST of I/O KERNAL + rts + + lda #$B0 + sta $C2 + lda $0200 + sta $C3 + lda $0201 + sta $C4 +W9173: + lda #>$A000 + sta $AF + ldy #<$A000 + sty $AE + lda ($C3),y + tax + bne :+ + jmp fill_loop +: jsr store_a_ff_to_ae + txa + bpl :+ + jmp W9200 +W918C: +: ldy #$02 + jsr _load_ae_rom_hidden + bpl @2 + lda #$05 + ora $AE + sta $AE + ldy #$00 +: lda ($C3),y + beq :+ + jsr _load_ae_rom_hidden + cmp ($C3),y + bne @2 + iny + cpy #$11 + bne :- + beq @1 +: cpy #$10 + beq :+ + jsr _load_ae_rom_hidden + cmp #$A0 + bne @2 +: iny + tya + jsr not_last_sector + ldy #$00 + lda $AE + and #$F0 + sta $AE + lda #$00 + sta ($C1),y + iny + sta ($C1),y + iny +: jsr _load_ae_rom_hidden + sta ($C1),y + iny + cpy #$20 + bne :- + tya + clc + adc $C1 + sta $C1 + bcc W9173 + inc $C2 + lda $C2 + cmp #$C0 + bcc W9173 +@1: + jmp W915D + +@2: + lda $AE + and #$F0 + clc + adc #$20 + sta $AE + bcc :+ + inc $AF +: lda $AF + cmp $AD + bcs @1 + jmp W918C + + +.segment "mysterybytes" + +; These bytes might just be some random padding, because the screenshot code starts at exactly $9500. +; This might also be code, but it doesn't look like it would be actually executable code. + + .byte $15, $03, $a0, $00, $84, $ac, $84, $ae + .byte $a9, $0c, $85, $ad, $a9, $c0, $85 + +.segment "junk0" + + + + .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF + .byte $FF, $FF, $FF, $FF, $FF, $FF, $1C + +.segment "ramcode" + + ; Installed to zeropage at $0060 + +WA421: + jmp $1D48 + + jmp $1D58 + + jsr $154D + jmp $B603 + + lda #$0D + jsr $1599 + jsr $1CDA + jsr $1D58 + jsr $137A + jsr $1CAD + jmp $B603 + + jsr $18DA + jsr $1EB1 + bcs @1 + ldx #$6E + ldy #$11 + lda #$49 + jsr _enable_fcbank0 + txa + beq :+ + jmp $18D4 +: jsr $12BF +@1: ldx #$FB ; init stack? + txs + lda #$58 + jsr _enable_fcbank0 + nop + nop + nop + jmp $8003 ; warmstart ?? + +.segment "mysterybytes2" + .byte $cd + .byte $19,$a1,$19,$ef,$19,$47,$1a,$66 + .byte $1a,$52,$1a,$5a,$1a,$73,$1a,$5d + .byte $1a,$96,$1a,$88,$1a,$71,$10,$21 + .byte $14,$27,$1a,$d0,$1f,$dd,$1f + +.segment "ramcode2" + +;WA489 + jsr $148D + sec + lda $0DC1 + sbc $9F + sta $0DC1 + bcs :+ + dec $0DC2 +: rts + + jsr $148D + clc + lda $0DC1 + adc $9F +WE4A4: + sta $0DC1 + bcc :+ + inc $0DC2 +: rts + + lda $0E04 + bpl :+ + clc + adc #$01 +: and #$0F + sec + adc $5700,x + sta $9F + rts + + lda $0DC1 + cmp #$2A + bcc :+ + lda $0DC2 + cmp #$01 +: rts + + sei +: lda $D012 + cmp #$FB + bcc :- + cli + rts + + ldy #$01 + clc + lda #$2A + adc $0DBE + tax + bcc :+ + iny +: sty $FA + ldy $0DBF + lda #$03 + jsr _enable_fcbank0 + ldx $FE + ldy $FF + stx $0DC7 + sty $0DC8 + rts + +WE4F6: + ldy #$00 + lda ($8B),y + sta ($35),y + tax + tya + iny + sta ($35),y + inc $8B + bne :+ + inc $8C +: inc $35 + bne :+ + inc $36 +: rts + + rts + + ldy #$00 + lda ($8B),y + cmp #$0D + beq WE4F6 + rts + +WE518: + lda $8B + bne :+ + dec $8C +: dec $8B + lda $35 + bne :+ + dec $36 +: dec $35 + ldy #$00 + lda ($35),y + sta ($8B),y + tax + tya + sta ($35),y + rts + + dec $36 + ldy #$FF + lda ($35),y + inc $36 + cmp #$0D + beq WE518 + rts + + lda $A3 + bpl :+ + clc + adc #$01 +: and #$0F + sta $96 + ldy #$00 + sty $0DC1 + sty $0DC2 +@1: lda ($C3),y + beq @x + tax + sec + lda $5700,x + adc $96 + adc $0DC1 + sta $0DC1 + bcc :+ + inc $0DC2 +: iny + bne @1 +@x: rts + + ldy #0 + lda #$FF + sta ($35),y + tya + iny + sta ($35),y + inc $35 + bne :+ + inc $36 +: rts + + lda $35 + bne :+ + dec $36 +: dec $35 + ldy #$00 + lda ($35),y + tax + tya + sta ($35),y + rts + + inc $8B + bne :+ + inc $8C +: clc + rts + + dec $36 + ldy #$00 +: dey + lda ($35),y + cmp #$FF + bne :- + tya + eor #$FF + tax + sta $C3 + inc $36 + ldy $36 + sec + lda $35 + sbc $C3 + sta $C3 + bcs :+ + dey +: sty $C4 + rts + + ldy #0 + sta ($35),y + inc $35 + bne :+ + inc $36 +: tya + sta ($35),y + rts + + sec + lda #$2A + sbc $0DC1 + sta $8D + lda #$01 + sbc $0DC2 + sta $8E + jsr $165E + bcs @2 + jsr $1C5C + lda $8E + rts +@2: jsr $1C74 + lda $8E + rts + +WA5E7: + jsr $14F8 + jsr $1469 + lda #$01 + sta $0DCA + bne @1 + jsr $14F8 + jsr $1469 + lda #$00 + sta $0DCA + beq :+ + lda #$FF + sta $0DCA +: jsr $14F8 + jsr $1469 + inc $0DCA + cpx #$20 + bne :- + lda $0DCA + bne :+ + inc $0DCA + bne @1 +: jsr $14D6 +@1: jsr $154D + jsr $1323 + jsr $1CDA + lda $0DC9 + cmp $0DCB + bne :+ + jsr $1DF5 + dec $0DC9 + ldy $0DC9 + lda $0DE6,y + sta $0DBF +: jsr $1D58 + inc $0DC9 + ldy $0DC9 + lda $0DE6,y + sta $0DBF + lda $8B + sta $0DCD,y + lda #$00 + sta $0DC1 + sta $0DC2 + lda $0DCA + sta $8E + beq WE66D +: jsr $14D6 + jsr $147B + dec $8E + bne :- +WE66D: + jsr $1CAD + jmp $14B5 + + ldx $0DCA + beq @xc + dec $36 + ldy #$FE + bne :+ + ldx $0DCA + beq @xc + dec $36 + ldy #$FF +: lda ($35),y + cmp #$20 + beq @xs + dey + dex + bne :- + inc $36 +@xc: clc + rts + +@xs: inc $36 + sec + rts + + lda $35 + cmp #$01 + bne @rts + beq :+ + lda $35 + bne @rts +: lda $36 + cmp #$58 +@rts: rts + +WE6AA: + jsr $1681 + beq WE6D4 + jsr $14F8 + cpx #$20 + bcc WE6CB + cpx #$7E + bcc WE6AA + txa + eor #$A0 + cmp #$61 + bcc WE6CB + cmp #$7E + bcs WE6CB + ldy #$00 + sta ($8B),y + beq WE6AA +WE6CB: + cpx #$0D + beq WE6AA + jsr $156F + bcc WE6AA +WE6D4: + jmp $154D + + lda #$00 + sta $0DC9 + sta $0DCA + sta $0DC1 + sta $0DC2 + ldx $0E01 + ldy $0E02 + stx $0DBE + sty $0DBF + rts + +WE6F2: + jsr $15A7 + beq WE720 + jsr $14D6 + txa + beq WE71D + cpx #$0D + beq WE71D + inc $0DCA + jsr $147B + lda $A6 + cmp $0DC2 + bcc WE717 + bne WE6F2 + lda $0DC1 + cmp $A5 + bcc WE6F2 +WE717: + jsr $1469 + dec $0DCA +WE71D: + jsr $14F8 +WE720: + rts + +WE721: + lda $0DCA + beq @x + jsr $14F8 + txa + dec $0DCA + jsr $1469 + lda $0DC2 + cmp $A6 + bcc @x + bne WE721 + lda $A5 + cmp $0DC1 + bcc WE721 +@x: rts + + lda $0DC2 + cmp $A6 + bcc WE6F2 + bne WE721 + lda $A5 + cmp $0DC1 + bcs WE6F2 + bcc WE721 + cpy $0DC9 + bcs WE7B8 + sty $F7 + sec + lda $0DC9 + sbc $F7 +WE760: + sta $F7 + inc $F7 + lda #$00 + sta $A5 +@3: jsr $14F8 + cpx #$FF + bne @3 + jsr $156F + jsr $1681 + beq @4 + ldy $0DC9 + lda $8B + ldx $A5 + bne @1 + cmp $0DCD,y + beq @2 + inc $A5 +@1: lda #$00 + sta $0DCD,y +@2: dec $F7 + beq @4 + dec $0DC9 + ldy $0DC9 + lda $0DE6,y + sta $0DBF + bne @3 +@4: jsr $154D + dec $0DC9 + jsr $1D58 + inc $0DC9 + lda #$00 + sta $0DCA + sta $0DC1 + sta $0DC2 + jmp $14B5 + +WE7B8: + sec + tya + sbc $0DC9 + sta $F7 +WE7BF: + jsr $15A7 + beq @1 +: jsr $14D6 + jsr $147B + dec $8E + bne :- +@1: ldy #$00 + lda ($8B),y + beq WE760 + jsr $14EF + jsr $154D + lda #$00 + sta $0DCA +WE7DF: + sta $0DC1 + sta $0DC2 + inc $0DC9 + ldy $0DC9 + lda $0DE6,y + sta $0DBF + dec $F7 + bne WE7BF + jmp $14B5 + + lda $0DC0 + beq WE80C + asl + tax + lda $1447,x + sta $A4 + lda $1448,x + sta $A5 + jmp ($00A4) + +WE80C: + jmp $1CAD + + sta $A3 + sta $A6 + stx $A4 + sty $A5 +WE817: + ldy #$06 + lda ($A4),y + cmp #$23 + bne :+ + iny + lda ($A4),y + cmp $A3 + bne WE84C + beq WE82F +: iny + lda ($A4),y + cmp $A3 + beq WE840 +WE82F: + ldy #$00 + lda ($A4),y + tax + iny + lda ($A4),y + stx $A4 + sta $A5 + bne WE817 + ldy $A6 + rts + +WE840: + ldy #$06 + lda ($A4),y + ora #$02 + sta ($A4),y + ldy #$09 + bne WE856 +WE84C: + ldy #$06 + lda ($A4),y + and #$FD + sta ($A4),y + ldy #$0A +WE856: + lda ($A4),y + pha + ldy #$08 + lda ($A4),y + sta $A3 + ldy #$02 + lda ($A4),y + tax + iny + lda ($A4),y + stx $A4 + sta $A5 + ldy $A3 + pla + sta ($A4),y + ldy $A6 + rts + + lda $B6 + cmp #$08 + bcs WE891 + lda $B5 +WE87B: + bne :+ + jsr $18C3 + lda #$00 + sta $0DC0 + lda #$3C + jsr _enable_fcbank0 + jsr $18CC + jsr $17D8 +: rts + +WE891: + ldy #$00 + lda $B6 + ldx $0DCB + inx +: cmp $0DE6,y + bcc WE8A4 + iny + dex + bpl :- + ldy #$00 +WE8A4: + tya + beq @1 + dey + sec + ldx $B5 + lda $B4 + sbc $0E01 + bcs :+ + dex + bpl :+ + lda #$00 + tax +: sta $A5 + stx $A6 + sta $0DC3 + stx $0DC4 + cpy $0DC9 + beq :+ + jsr $1733 + lda $0DC3 + ldx $0DC4 + sta $A5 + stx $A6 +: jsr $1721 + jsr $1323 + jsr $1CAD +@1: lda $03C8 + beq @1 + rts + + lda #$50 + jsr _enable_fcbank0 + jsr $18DA + rts + + jsr $18D4 + lda #$57 + jmp _enable_fcbank0 + + lda #$43 + sta $D015 ; Sprites Abilitator + rts + + lda #$03 + sta $D015 ; Sprites Abilitator + rts + + ldy #$FF + lda $0E02 +: iny + sta $0DE6,y + clc + adc $0E03 + cmp #$BC + bcc :- + sty $0DCB + iny + lda #$C8 + sta $0DE6,y + rts + + sei + ldx #<$EA31 + ldy #>$EA31 + stx $0314 ; Vector: Hardware Interrupt (IRQ) + sty $0315 ; Vector: Hardware Interrupt (IRQ) + lda #$F0 + sta $D01A ; IRQ mask register + cli + rts + + sei + ldx #<$DE21 + ldy #>$DE21 + stx $0314 ; Vector: Hardware Interrupt (IRQ) + sty $0315 ; Vector: Hardware Interrupt (IRQ) + lda #$F1 + sta $D01A ; IRQ mask register + cli + rts + + ldx #$FF + lda $1070 + ldy $0DBD + cpy #$08 + bcc WE94E + tay + beq WE968 +WE94E: + ldx #$5F + ldy #$10 + sta $8D + stx $8E + sty $8F + lda $0DBD + sta $F7 + ldx #$00 + ldy #$58 + lda #$53 + jsr _enable_fcbank0 + ldx $8F +WE968: + stx $0DFF + ldx $AE + ldy $AF + stx $0DC3 + sty $0DC4 + rts + + ldx #$FF + lda $1070 + ldy $0DBD + cpy #$08 + bcc WE985 + tay + beq WE9B4 +WE985: + ldx #$5F + ldy #$10 + sta $8D + stx $8E + sty $8F + ldx $8B + ldy $8C + stx $A8 + sty $A9 + lda #$A8 + sta $F7 + ldx #$FF + ldy #$7F + lda $0DBD + sta $AA + lda #$54 + jsr _enable_fcbank0 + ldx #$00 + lda $0DBD + cmp #$08 + bcc WE9B4 + ldx $8F +WE9B4: + stx $0DFF + rts + +WE9B8: + jsr $14D6 + txa + bne WE9B8 + jmp $14F8 + + jsr $1679 + beq @x1 +@l: jsr $18DA + jsr $16B7 + jsr $14B5 + jsr $1323 + jsr $1CAD + ldy $0DCB + lda #$00 +: sta $0DCD,y + dey + bpl :- + jsr $168A + jsr $B609 + jsr $1323 + jsr $18D4 +@x1: rts + + jsr $1EB1 + bcs @5 + jsr $1AFD + txa + beq :+ + rts + +: jsr $12BF +@5: jsr $1A03 + ldx #$00 + stx $C6 + ldy #$58 + stx $35 + sty $36 + jsr $154D + jmp $19F9 + + ldx $0DC3 + ldy $0DC4 + stx $35 + sty $36 + ldx #$FF + ldy #$7F + stx $8B + sty $8C + bne @l + ldx #$05 + ldy #$10 + lda #$02 + jsr _enable_fcbank0 + ldx #$9A + ldy #$B3 + lda #$08 + jsr _enable_fcbank0 + ldx #$9F + ldy #$10 + lda #$02 + jsr _enable_fcbank0 + ldx #$9A + ldy #$B3 + lda #$08 + jmp _enable_fcbank0 + + lda $0E04 + eor #$10 + sta $0E04 + sta $A3 + and #$10 + beq @4 + ldy #$6E +: lda #$06 + sta $5710,y + dey + bpl :- + bmi @3 +@4: jsr $1123 +@3: jmp $19A6 + + lda $0E04 + eor #$80 + sta $0E04 + clc + bcc :+ + lda $0E04 +: sta $A3 + jmp $19A6 + + jsr $18E0 + jsr $18DA + jsr $1A03 + jmp $19A6 + + lda $0E05 + eor #$01 + sta $0E05 + sta $8F + jmp $19A6 + + jsr $168A + jsr $18C3 + jsr $18FB + jsr $1B30 + jsr $190D + jsr $18CC + jmp $19A6 + + lda $0DFF + beq :+ + jsr $1AF4 + jmp $19DC +: jmp $19EF + + jsr $18C3 + jsr $1EFB + jsr $18CC + jsr $1CAD + lda $0DC0 + cmp #$02 + bne @2 + rts + +@2: jsr $168A + lda #$00 + sta $0DFF + jsr $18C3 + jsr $1956 + jsr $18CC + lda $0DFF + beq :+ + jsr $1AF4 +: jmp $19A6 + + lda #$80 + pha + lda #$0B + pha + ldy $DE00 + lda #$40 + jmp _jmp_bank + + ldx #$03 + jsr $1AC6 + lda $90 ; Statusbyte ST of I/O KERNAL + bmi :+ + ldx #$00 + lda $0200 + cmp #$30 + bne :+ + lda $0201 + cmp #$30 + beq @1 +: dex +@1: stx $8F + stx $0DFF + rts + + jsr $18DA +WEB17: + ldx #$39 + ldy #$11 + bne WEB48 + jsr $18DA + ldx #$92 + ldy #$11 + bne WEB48 + jsr $18DA + ldx #$BA + ldy #$11 + bne WEB48 + jsr $18DA + ldx #$F7 + ldy #$11 + bne WEB48 + jsr $18DA + ldx #$40 + ldy #$12 + bne WEB48 + jsr $18DA + ldx #$67 + ldy #$12 +WEB48: + lda #$49 + jsr _enable_fcbank0 + jmp $18D4 + + lda #$00 + sta $90 ; Statusbyte ST of I/O KERNAL + jsr $FF90 ; Routine: Control KERNAL messages + ldx #$0B +WEB59: + jsr $1AC6 + ldx #$0B + jsr $1AC6 + lda $90 ; Statusbyte ST of I/O KERNAL + bmi WEB9B + jsr $1B85 + tya + beq WEB9B + ldy #$00 + sty $A6 ; Pointer: I/O Buffer of tape +@1: lda ($8B),y + cmp #$0D + beq WEB8B + cmp #$5F + bne :+ + lda #$0C +: sta $0200 + ldx #$0C + jsr $1AC6 + inc $A6 + ldy $A6 + dec $A4 + bne @1 +WEB8B: + lda #$0D + sta $0200 + ldx #$0C + jsr $1AC6 + jsr $1BB4 + jmp $1B45 + +WEB9B: + ldx #$0D + jsr $1AC6 + lda #$C0 + jmp $FF90 ; Routine: Control KERNAL messages + + lda $0E00 + sta $A4 + ldy #$00 + sty $A8 +@4: lda ($8B),y + beq @5 + iny + cmp #$0D + beq @5 + ldx $0E05 + beq :+ + cmp #$20 + bne @6 +: sty $A8 +@6: dec $A4 + bne @4 + ldy $A8 + bne @5 + ldy $0E00 + bne @5 +@5: sty $A4 + sty $A8 + rts + + clc + lda $8B + adc $A8 + sta $8B + bcc :+ + inc $8C +: rts + + ldx #$00 + ldy #$00 + lda #$02 + jsr _enable_fcbank0 + lda #$C8 + sta $F9 + lda #$05 + jsr _enable_fcbank0 + lda #$01 + sta $FA + ldx #$3F + ldy #$00 + lda #$03 + jsr _enable_fcbank0 + lda #$05 + jsr _enable_fcbank0 + ldx #$00 + ldy #$C7 + lda #$02 + jsr _enable_fcbank0 + ldx #$9F + stx $F8 + lda #$04 + jsr _enable_fcbank0 + ldx #$9F + ldy #$C7 + lda #$02 + jsr _enable_fcbank0 + lda #$04 + jsr _enable_fcbank0 + rts + + lda $A3 + bpl :+ + clc + adc #$01 +: and #$0F + sta $96 + ldy #$00 + sty $9E + sty $9F + sty $C4 +@l: lda ($8B),y + tax + beq @1 + cmp #$0D + beq @1 + tax + sec + lda $5700,x + adc $96 + adc $9E + sta $9E + bcc :+ + inc $9F +: iny +@1: lda $8F + beq :+ + cpx #$21 + bcs @3 +: lda $8E + cmp $9F + bcc @x + bne @2 + lda $9E + cmp $8D + beq @2 + bcs @x +@2: sty $C4 +@3: txa + beq @y + cpx #$0D + beq @y + bne @l ; always +@x: ldy $C4 + ldx #$01 + rts +@y: ldx #$00 + rts + + jsr $1C05 + tya + bne :+ + txa + beq :+ + lda #$00 + sta $8F + jsr $1C05 + lda $0E05 + sta $8F +: sty $8E + rts + + jsr $1C05 + sty $8E + rts + +kungfu: + ldy #$00 + sty $8D + lda $8E + beq @rts +: lda ($8B),y + tax + cmp #$0D + beq @rts + lda #$19 + jsr _enable_fcbank0 + inc $8D + ldy $8D + cpy $8E + bcc :- +@rts: rts + +shogun: + ldy $8E + lda ($8B),y + cmp #$0D + bne :+ + inc $8E +: clc + lda $8B + adc $8E + sta $8B + bcc :+ + inc $8C +: rts + + clc + lda #$31 + adc $0DBF + sta $D00D ; Position Y sprite 6 + clc + lda #$17 + adc $0DBE + adc $0DC1 + tay + bcs WECE7 + lda $0DC2 + beq WECEE +WECE7: + lda $D010 ; Position X MSB sprites 0..7 + ora #$40 + bne WECF3 +WECEE: + lda $D010 ; Position X MSB sprites 0..7 + and #$BF +WECF3: + sta $D010 ; Position X MSB sprites 0..7 + sty $D00C ; Position X sprite 6 + rts + + ldx #$7B + lda #$19 + jsr _enable_fcbank0 + sec + lda $0DC7 + sbc $FE + sta $A4 + lda $0DC8 + sbc $FF + bmi @rts + beq :+ + lda #$20 +: lsr $A4 + lsr $A4 + lsr $A4 + ora $A4 + sta $A4 + lda $FE + and #$07 + sta $A7 + eor #$07 + sta $A5 + lda $FF + sta $A8 + ldy #$00 + jsr $1D28 + ldx $A8 + inx + stx $FF + lda $FE + tax + and #$F8 + sta $FE + txa + and #$07 + sta $A5 + eor #$07 + sta $A7 + ldy #$40 + lda $A4 + sta $A6 +@2: lda #$00 + ldx $A5 +@1: sta ($FE),y + iny + bne :+ + inc $FF +: dex + bpl @1 + tya + clc + adc $A7 + bcc :+ + inc $FF +: tay + dec $A6 + bpl @2 +@rts: rts + + ldx $8B + ldy $8C + stx $0DC5 + sty $0DC6 + jsr $1C97 + jmp $1D62 + + ldx $8B + ldy $8C + stx $0DC5 + sty $0DC6 + lda $0DBF + ldx $0DC7 + ldy $0DC8 + sta $0DB8 + stx $0DB9 + sty $0DBA + lda $0DC9 + sta $0DCC + ldy $0DCC + cpy $0DCB + beq WEDE3 + iny + inc $0DCC + lda $8B + beq :+ + cmp $0DCD,y + beq WEDE3 +: sta $0DCD,y + lda $0DE6,y + sta $0DBF + jsr $14B5 + ldx $0DBE + ldy $0DBF + lda #$02 + jsr _enable_fcbank0 + ldx #$2A + ldy #$01 + stx $8D + sty $8E + jsr $1C5C + jsr $1C7A + jsr $1CDA + ldy #$00 + lda ($8B),y + beq :+ + jsr $1C97 +: jmp $1D7A + +WEDE3: + lda $0DB8 + ldx $0DB9 + ldy $0DBA + sta $0DBF + stx $0DC7 + sty $0DC8 + ldx $0DC5 + ldy $0DC6 + stx $8B + sty $8C + rts + +samurai: + lda $0DCB + sta $A4 + lda #$2A + lsr + lsr + lsr + ldx #$01 + beq :+ + ora #$20 +: sta $F7 + inc $F7 + rts + +ninja: + lda $0E02 + sta $C3 + jsr $1DE0 +@3: lda $0E03 + sta $A9 +@2: ldx $0E01 + ldy $C3 + lda #$02 + jsr _enable_fcbank0 + ldx $FE + ldy $FF + stx $A7 + sty $A8 + ldx #$00 + ldy $0E03 + lda #$0C + jsr _enable_fcbank0 + ldx $FE + ldy $FF + stx $A5 + sty $A6 + inc $C3 + ldy #$00 + ldx $F7 +@1: lda ($A5),y + sta ($A7),y + tya + clc + adc #$08 + tay + bne :+ + inc $A6 + inc $A8 +: dex + bne @1 + dec $A9 + bne @2 + dec $A4 + bne @3 + ldy $0DCB + lda #$00 + sta $0DCD,y + rts + + ldy $0DCB + lda $0DE6,y + sta $C3 + jsr $1DE0 +@5: lda $0E03 + sta $A9 +@6: dec $C3 + ldx $0E01 + ldy $C3 + lda #$02 + jsr _enable_fcbank0 + ldx $FE + ldy $FF + stx $A7 + sty $A8 + ldx #$00 + ldy $0E03 + lda #$0C + jsr _enable_fcbank0 + ldx $FE + ldy $FF + stx $A5 + sty $A6 + ldy #$00 + ldx $F7 +@4: lda ($A7),y + sta ($A5),y + tya + clc + adc #$08 + tay + bne :+ + inc $A6 + inc $A8 +: dex + bne @4 + dec $A9 + bne @6 + dec $A4 + bne @5 + ldx $0DCB + dex +: lda $0DCD,x + sta $0DCE,x + dex + bpl :- + rts + + lda $35 + cmp #$01 + bne :+ + lda $36 + cmp #$58 + bne :+ + lda $8B + cmp #$FF + bne :+ + lda $8C + cmp #$7F + bne :+ + sec + rts +: clc + rts + +WEEED: + ldx #$A0 + ldy #$46 + sty $A3 + stx $A4 + ldx #$50 + ldy #$3C + jmp _enable_fcbank0 + +WEEFC: + ldx #$50 + ldy #$3C + lda #$02 + jsr _enable_fcbank0 + ldx #$A0 + ldy #$46 + rts + + sec + lda $B4 + sbc $C000 + sta $9F + sec + lda $B6 + sbc $C001 + sta $96 + rts + + lda #$4B + jsr $1ECD + jsr $1EDC + lda #$08 + jsr _enable_fcbank0 + ; ???? + ldx #$51 + ldy #$3D + lda #$02 + jsr _enable_fcbank0 + ldx #$9E + ldy #$44 + lda #$06 + jsr _enable_fcbank0 + ldx #$50 + ldy #$3C + stx $C000 + sty $C001 + ldx #$EE + ldy #$0F +WEF48: + lda #$23 + jsr _enable_fcbank0 + ldx $C014 + ldy $C015 + bne WEF48 + ; ????? + ldx #$5F + ldy #$53 + lda #$02 + jsr _enable_fcbank0 + ldx #$82 + ldy #$0A + lda #$09 + jsr _enable_fcbank0 + jsr $1EDC + lda #$09 + jsr _enable_fcbank0 + jsr $1F5C + lda #$4C + jsr $1ECD + lda #$00 + sta $C6 + rts + +WEF7C: + ldx #$50 + ldy #$3C + stx $C000 + sty $C001 +@1: lda $03C8 + bne @1 + jsr $1EEA + ldx #$EE + ldy #$0F +: lda #$22 + jsr _enable_fcbank0 + lda #$35 + jsr _enable_fcbank0 + bcs :+ + ldx $C014 + ldy $C015 + bne :- + beq @1 +: ldy #$1E +: lda $0100,y + sta $5790,y + dey + bpl :- + lda #$37 + jsr _enable_fcbank0 + ldy #$1E +: lda $5790,y + sta $0100,y + dey + bpl :- + ldy #$0F + lda ($9B),y + cmp #$03 + bne :+ + lda $03C8 + sta $D00D ; Position Y sprite 6 + beq WEF7C +: sta $0DC0 + ldy #$FF +WEFD8: + iny + lda $104E,y + cmp #$61 + bcc :+ + cmp #$7B + bcs :+ + eor #$20 +: sta $105F,y + tax + bne WEFD8 + sty $1070 + rts + + jsr $1B18 + txa + bne :+ + jsr $10F0 + jsr $19EF +: rts + + jmp $1B21 + +.segment "mysterybytes3" + + .byte $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $33, $33, $33, $33, $33, $33, $33, $33 + .byte $33, $33, $33, $33, $33, $33, $33, $33 + .byte $00 + +.segment "mysterybytes4" + .byte $00, $00, $00, $00, $FF, $FF, $FF, $FF + .byte $00, $00, $00, $00, $FF, $FF, $FF, $FF + .byte $00, $00, $00, $00, $FF, $FF, $FF, $FF + .byte $00, $00, $00, $00, $FF, $FF, $FF, $FF + .byte $00, $00, $00, $00, $FF, $FF, $FF, $FF + .byte $00, $00, $00, $00, $FF, $FF, $FF, $FF + .byte $00, $00, $00, $00, $FF, $FF, $FF, $FF + .byte $00, $00 + +.segment "mysterybytes5" + .byte $FF, $FF, $FF, $00, $00, $00, $00, $FF + .byte $F7, $FF, $FF, $00, $00, $00, $00, $FF + .byte $FF, $FF, $FF, $00, $00, $00, $00, $FF + .byte $FF, $FF, $FF, $00, $00, $00, $00, $FF + .byte $FF, $FF, $FF, $00, $00, $00, $00, $FF + .byte $FF, $FF, $FF, $00, $00, $00, $00, $FF + .byte $FF, $FF, $FF, $00, $00, $00, $00, $FF + .byte $FF, $FF, $FF, $00, $00, $00, $00, $FF + .byte $FF, $FF, $FF, $00, $00, $00, $00, $FF + .byte $FF, $FF, $FF, $00, $00 + diff --git a/bank3/persistent.i b/bank3/persistent.i new file mode 100644 index 0000000..08441bd --- /dev/null +++ b/bank3/persistent.i @@ -0,0 +1,14 @@ +.import _jmp_bank +.import autofire_lda_dc00 +.import autofire_lda_dc01 +.import autofire_ldx_dc00 +.import autofire_ldx_dc01 +.import autofire_ldy_dc00 +.import autofire_ldy_dc01 +.import t_freezer_init +.import _jmp_bank,_enable_fcbank0,_disable_fc3rom_set_01 +.import _load_ae_rom_hidden +.import ultimax_fbe4 +.import ultimax_highlight_selected_menu +.import _freezer_upd_sprptr_16k +.import _show_view_menu diff --git a/bank3/persistent.s b/bank3/persistent.s new file mode 100644 index 0000000..ce2297e --- /dev/null +++ b/bank3/persistent.s @@ -0,0 +1,261 @@ +; --------ø-------------------------------------------------------- +; I/O Area ROM +; ---------------------------------------------------------------- +; This is a max. 512 byte section that lives at $1E00-$1FFF of +; bank 0 of the ROM, and will also be mapped into the I/O extension +; area at $DE00-$DFFF, so it's always visible. + +; It contains soms trampolines to be able to switch from/to Ultimax +; mode for the freezer and contains the autofire code for the joystick + + .setcpu "6502x" + +.include "../core/fc3ioreg.i" +.include "../core/kernal.i" + +.import freezer_init +.import freezer_exec_menu +.import freezer_update_spritepointers +.import show_view_menu +;.import freezer_exec_bank + +.segment "romio1l" +; +; +; ROMIO1 area ($DE00) +; +; + +fc_bank_id: + .byte fcio_bank_3|fcio_nmi_line + +; +; Jump into a bank of the FC3 ROM +; +; Jumps to a routine in the FC3 ROM of which the address is on the stack +; and the bank number in A. +; + +.global _jmp_bank +_jmp_bank: + sta fcio_reg + rts + +.global _enable_fcbank0 +_enable_fcbank0: ; $DE05 + pha + lda #fcio_bank_0|fcio_c64_16kcrtmode|fcio_nmi_line +a_to_fcio_pla: + sta fcio_reg + pla + rts + +; _disable_fc3rom: Hides the FC3 ROMS from memory +; _disable_fc3rom_set_01: Stores Y into $01 and hides the FC3 ROMS from memory +; + +.global _disable_fc3rom_set_01 +_disable_fc3rom_set_01:; $DE0D + sty $01 +.global _disable_fc3rom +_disable_fc3rom: ; $DE0F + pha + lda #fcio_bank_0|fcio_c64_crtrom_off|fcio_nmi_line + bne a_to_fcio_pla ; always taken + + ; padding + .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF + .byte $FF,$FF,$FF,$FF + +; +; Do an "lda($AE),y" with ROMs disabled and interrupts off +; + +.global _load_ae_rom_hidden +_load_ae_rom_hidden: ; $de20 + sei + lda #$35 + sta $01 + lda ($AE),y + pha + lda #$37 + sta $01 + pla + cli + rts + +.segment "romio1h" + +.global _freezer_upd_sprptr_16k +_freezer_upd_sprptr_16k: + lda #fcio_bank_3|fcio_c64_16kcrtmode + sta fcio_reg + jsr freezer_update_spritepointers ; jump into bank 3 +ultimax_bank3_rts: + lda #fcio_bank_3|fcio_c64_ultimaxmode + sta fcio_reg + rts + +; +; Go to ultimax mode, execute the freezer menu and return to 16K mode +; + +.global freezer_ultimax_exec_menu +freezer_ultimax_exec_menu: + jsr ultimax_bank3_rts + jsr freezer_exec_menu +bank3_16kmode: + ldx #fcio_bank_3|fcio_c64_16kcrtmode + stx fcio_reg + rts + +; +; Go to 16k mode, execute $bc5b and return to ultimax mode +; +.global _show_view_menu +_show_view_menu: + jsr bank3_16kmode + jsr show_view_menu + jsr ultimax_bank3_rts + jmp freezer_exec_menu + +; +; Go to ultimax mode, execute $fbe4 and return to 16K mode +; + +.global ultimax_fbe4 +ultimax_fbe4: + jsr ultimax_bank3_rts + jsr $FBE4 + jmp bank3_16kmode + +; +; Go to ultimax mode, execute $fb98 and return to 16K mode +; + +.global ultimax_highlight_selected_menu +ultimax_highlight_selected_menu: + jsr ultimax_bank3_rts + jsr $FB98 + jmp bank3_16kmode + + +.segment "romio2l" + +.global autofire_ldy_dc01 +autofire_ldy_dc01: + pha + tya + jsr autofire_lda_dc01 +autofire_ldy_exit: + tay + pla + cpy #0 + rts + +.global autofire_ldx_dc01 +autofire_ldx_dc01: + pha + txa + jsr autofire_lda_dc01 +autofire_ldx_exit: + tax + pla + cpx #0 + rts + +.global autofire_ldy_dc00 +autofire_ldy_dc00: + pha + tya + jsr autofire_lda_dc00 + jmp autofire_ldy_exit + +.global autofire_ldx_dc00 +autofire_ldx_dc00: + pha + txa + jsr autofire_lda_dc00 + jmp autofire_ldx_exit + + cpy #$01 + beq autofire_lda_dc01 + bne autofire_lda_dc00 + cpx #$01 + beq autofire_lda_dc01 +.global autofire_lda_dc00 +autofire_lda_dc00: + lda $DC00 ; Data port A #1: keyboard, joystick, paddle, optical pencil + jmp autofire_chkbutton + +.global autofire_lda_dc01 +autofire_lda_dc01: + lda $DC02 ; Data direction register port A #1 + pha + lda #$00 + sta $DC02 ; Data direction register port A #1 + lda $DC01 ; Data port B #1: keyboard, joystick, paddle + sta $0122 ; Save to tmp location in stack memory + pla + sta $DC02 ; Data direction register port A #1 + lda $0122 ; Load from tmp location + pha + and #$10 ; Fire button pressed? + beq autofire_button_pressed + pla + lda $DC01 ; Data port B #1: keyboard, joystick, paddle + rts + + lda $0122 +autofire_chkbutton: + pha + and #$10 ; Fire button pressed? + beq autofire_button_pressed +pla_rts: + pla + rts + +autofire_button_pressed: + lda $0120 + bne autofire_signal + dec $0121 + bne pla_rts + lda #$02 + sta $0120 + sta $0121 + bne pla_rts ; Always +autofire_signal: + dec $0121 + beq autofire_signal_press + pla + ora #$10 ; Unpress the button + rts + +autofire_signal_press: + lda #$00 + sta $0120 + lda #$01 + sta $0121 + pla + rts + +.global freezer_set_c64and_fc3_rts +freezer_set_c64and_fc3_rts: + sta fcio_reg + sty $01 + rts + + .segment "romio2h" + +.global t_freezer_init +t_freezer_init: + stx fcio_reg + sta $DD0D ; Interrupt control register CIA #2 + jmp freezer_init ; Continue freezer init in 16K crt mode + +bank1_jump: + lda #fcio_bank_1 | fcio_c64_crtrom_off |fcio_nmi_line ; goto_desktop + sta fcio_reg ; Execution continues in bank 1 +reset_c64: + jmp START ; Routine: Startup + diff --git a/bank3/screenshot.s b/bank3/screenshot.s new file mode 100644 index 0000000..64c7720 --- /dev/null +++ b/bank3/screenshot.s @@ -0,0 +1,1958 @@ +;***************************************************************************** +; +; This code has to do with creating screenshots. The code in the segment +; "screenshotcode" is copied to $5000 when a screenshot is printed. +; +; The code in segment "printersettings" prepares the screen shot and then +; jumps to the printer settings window that is located in bank 2. +; +;***************************************************************************** + + .setcpu "6502x" + +.include "../core/kernal.i" +.include "../core/fc3ioreg.i" +.include "persistent.i" + +.import __screenshotcode_RUN__, __screenshotcode_LOAD__,__screenshotcode_SIZE__ +.import __copycode_LOAD__,__copycode_RUN__,__copycode_SIZE__ +.import __ramload_LOAD__,__ramload_RUN__,__ramload_SIZE__ + + +print_graphmode_val := $30 +print_horizontal_size := $31 +print_vertical_size := $32 +print_sideways_flag := $35 +print_color_flag := $36 +print_8p24p_flag := $37 +; $00 Epson +; $40 NEC P +; $80 CBM +printer_type_flags := $3C + +; $00 = Commodore +; $01 = Centronics +; $02 = RS-323 +printer_interface := $0200 + +; $00 = CBM Compatible +; $01 = EPSON Compatible +; $02 = NEC P Series +printer_type := $0201 + +; $00 = yes +; $01 = no +print_colors := $0202 + +; $00 = no +; $01 = yes +print_sideways := $0203 + +; horizontal size - 1 +print_horz_size := $0204 + +; vertical size - 1 +print_vert_size := $0205 + +; $00 = 8P Single Density +; $01 = 8P Double Density +; $02 = 8P High Speed, DD +; $03 = 8P Quadruple Density +; $04 = 8P CRT Graphics +; $05 = 8P CRT Graphics II +; $06 = 24P Single Density +; $07 = 24P Double Density +; $08 = 24P CRT Graphics II +; $09 = Triple Density +print_graphmode := $0206 + +; $00 = no +; $01 = yes +print_invert := $0207 + +.segment "screenshotcode" +; $9500 + sei + lda #<$EA31 + sta $0314 ; Vector: Hardware Interrupt (IRQ) + lda #>$EA31 + sta $0315 ; Vector: Hardware Interrupt (IRQ) + ldx #$00 + stx $D01A ; IRQ mask register + + ; + ; Backup zero page to $7000 + ; + ldx #$02 +: lda $00,x + sta $7000,x + inx + bne :- + ; Hide the FC3 + lda #fcio_nmi_line | fcio_c64_crtrom_off | fcio_bank_0 + sta fcio_reg + + lda $0B21 ; $D021 backup + and #$0F + sta $0B21 + lda $0B16 ; $D016 backup + and #$10 ; Isolate multi-colour bit + asl + asl + asl + sta $50 ; Multi-colour flag $00=off $80=on + lda $0B11 ; $D011 backup + and #$20 ; Isolate + asl + asl + sta $26 ; Bitmap modee flag $00=off $80=on + + ; + ; Swap memory from $0C00..$1BFF with $C000..$CFFF + ; + ldy #$00 + sty $AC + sty $AE + lda #$0C + sta $AD + lda #$C0 + sta $AF + ldx #$10 +: lda ($AC),y + pha + lda ($AE),y + sta ($AC),y + pla + sta ($AE),y + iny + bne :- + inc $AD + inc $AF + dex + bne :- + + ; Settings from settings screen + ldx printer_type + beq @1 + dex + beq @2 + lda #$40 ; NEC P series printer + .byte $2c ; BIT $xxxx, skip next instruction +@1: lda #$80 ; Commodore MPS printer + .byte $2c ; BIT $xxxx, skip next instruction +@2: lda #$00 ; EPSON printer + sta printer_type_flags + lda #$00 + ldx print_colors + bne :+ + lda #$80 +: sta print_color_flag + lda #$00 + ldx print_sideways + beq :+ + lda #$80 +: sta print_sideways_flag + ldx print_horz_size + inx + stx print_horizontal_size + ldx print_vert_size + inx + stx print_vertical_size + lda #$00 + ldx print_graphmode + cpx #$06 + bcc :+ + lda #$80 +: sta print_8p24p_flag ; 8P/24P flag + lda printer_graphmodes,x + sta print_graphmode_val + lda print_invert + beq :+ + lda #$FF +: sta $25 + ldx #$08 + bit printer_type_flags + bpl @4 + dex + lda #$E0 + ldy #$01 + bit print_color_flag + bpl :+ + lda #$80 + ldy #$02 +: sta $40 + sty $41 + lda #$FF + sta $46 +@4: stx $3D + lda print_horizontal_size + bit print_sideways_flag + bpl :+ + lda print_vertical_size +: sta $29 + bit print_color_flag + bmi :+ + jsr routine1 +: bit print_sideways_flag ; Sideways printing? + bmi @3 ; Then jump + jsr routine2 + jsr routine3 + jsr routine4 + jsr routine5 + +@map_in_bank_2: + ; + ; Printing has finished, now return to the settings screen + ; + ; Map in FC3 bank 2 + lda #fcio_nmi_line | fcio_bank_2 + sei + sta fcio_reg + lda #<$DE21 + sta $0314 + lda #>$DE21 + sta $0315 + + ; + ; Swap memory from $0C00..$1BFF with $C000..$CFFF + ; + ldy #$00 + sty $AC + sty $AE + lda #$0C + sta $AD + lda #$C0 + sta $AF + ldx #$10 +: lda ($AC),y + pha + lda ($AE),y + sta ($AC),y + pla + sta ($AE),y + iny + bne :- + inc $AD + inc $AF + dex + bne :- + + ; + ; Copy to $7000 back to zero page + ; + ldx #$02 +: lda $7000,x + sta $00,x + inx + bne :- + inx + stx $D01A ; IRQ mask register + cli + rts + +@3: jsr routine4 + jsr routine3 + jsr routine2 + jsr routine6 + jmp @map_in_bank_2 + +routine2: + ldx print_vertical_size + lda #$C8 + sta $33 + lda #$00 + sta $34 +@1: dex + beq _rts + lda $33 + clc + adc #$C8 + sta $33 + lda $34 + adc #$00 + sta $34 + jmp @1 + +routine4: + ldx print_horizontal_size + lda #$40 + sta $33 + lda #$01 + sta $34 +@1: dex + beq _rts + lda $33 + clc + adc #$40 + sta $33 + lda $34 + adc #$01 + sta $34 + jmp @1 + +_rts: rts + +routine3: + ldx #$00 + stx $43 + stx $44 + ldx $33 + ldy $34 +: sec + stx $45 + txa + sbc #$07 + tax + tya + sbc #$00 + tay + bcc :+ + inc $43 + bne :- + inc $44 + bne :- +: lda #$00 + ldx $45 + beq @1 +: sec + rol + dex + bne :- +@1: sta $45 + rts + + +routine21: + lda $43 + bne :+ + dec $44 + bpl :+ + rts +: dec $43 + lda $43 + ora $44 + bne :+ + lda $45 + sta $46 +: lda #$00 + rts + +print_digit_at_17: + ldy #$11 + .byte $2c +print_digit_at_18: + ldy #$12 + eor #$30 + pha + clc + jsr PLOT + pla + jmp BSOUT + +routine1: + ; Clear $6000..$6AFF + lda #$00 + tay + sta $48 + ldx #>$6000 + stx $49 + ldx #$0B +: sta ($48),y + iny + bne :- + inc $49 + dex + bne :- + + ldx print_vertical_size +: clc + adc print_horizontal_size + dex + bne :- + stx $52 + ldx #$04 + pha +: asl + rol $52 + dex + bne :- + sta $51 + pla + asl + sta $47 + ldx #$00 + stx $3B + ldx #$04 +: asl + rol $3B + dex + bne :- + clc + adc #$00 + sta $3A + lda $3B + adc #$60 + sta $3B + + ldx #$0F +@2: lda tabel4,x + tay + beq @3 + lda #$00 + sta $48 + sta $49 +@1: clc + adc $47 + sta $48 + bcc :+ + inc $49 +: dey + bne @1 + ldy #$04 +: lsr $49 + ror + dey + bne :- +@3: sta end_of_text,x + dex + bpl @2 + ldy #$0F +@5: lda end_of_text,y + beq @4 + jsr routine7 +: lda #$01 + sta ($48),y + jsr add_10_to_48w + dex + beq @4 + lda #$01 + sta ($53),y + jsr routine9 + dex + bne :- +@4: dey + bpl @5 + lda print_horizontal_size + asl + asl + asl + asl + ldx #$10 + bit print_sideways_flag + bpl :+ + tax + lda #$10 +: sta $27 + stx $28 + rts + +routine7: + sta $11 + lda #$00 + sta $48 + clc + adc $51 + sta $53 + lda #$60 + sta $49 + adc $52 + sta $54 + sec + lda $3A + sbc $53 + sta $53 + lda $3B + sbc $54 + lsr + sta $54 + ror $53 + lda $53 + and #$F0 + clc + adc #$00 + sta $53 + lda #$60 + adc $54 + sta $54 + clc + lda $53 + adc $51 + sta $53 + lda $54 + adc $52 + sta $54 + ldx #$00 + stx $39 + lda $47 + dex +: sec + inx + sta $10 + sbc $11 + bcs :- + lda $10 + beq :+ + inx +: txa + ldx #4 +: asl + rol $39 + dex + bne :- + sta $38 + lda $39 + ldx $11 + rts + +add_10_to_48w: + clc + lda $48 + adc #$10 + sta $48 + lda $49 + adc #$00 + sta $49 + rts + +routine9: + clc + lda $53 + adc #$10 + sta $53 + lda $54 + adc #$00 + sta $54 + lda $53 + cmp $3A + lda $54 + sbc $3B + bcc :+ + lda #$00 + clc + adc $51 + sta $53 + lda #$60 + adc $52 + sta $54 +: rts + +zero_48w: + ldy #$00 + sty $48 + sty $49 + rts + +routine38: + inc $48 + bne :+ + inc $49 +: lda $48 + cmp #$80 + lda $49 + sbc #$02 + rts + +W981C: + jsr c3w_to_c1w + jsr zero_48w +LL3: jsr zero_3ew +: jsr routine13 + jsr routine14 + bcc @1 + jsr routine15 + jsr routine17 + bne :- + jsr routine38 + bcs W534E +@1: jsr routine37 + bne LL3 + jsr routine23 + lda $DC01 ; Data port B #1: keyboard, joystick, paddle + cmp #$7F + beq W534E + jsr routine24 + bne LL3 +W534E: + jsr close_all + lda #$01 + ldy #$0A + jsr routine22 + lda #$0D + jsr BSOUT + jmp close_all + +routine5: + jsr routine20 + jsr routine39 + bit printer_type_flags + bpl W986E + ; Commodore MPS + bit print_color_flag + bmi W981C +W986E: + bit print_color_flag + bpl :+ + lda #$0A + jsr BSOUT +: lda $06 + sta $07 + lda #$00 + sta $10 +W987F: + lda #$00 + sta $11 +W9883: + lda $10 + jsr routine32 + jsr zero_3ew +W988B: + jsr routine36 + lda $07 + sta $06 + jsr c3w_to_c1w +@4: jsr routine13 + jsr routine37 + bne :+ + jsr routine23 +: inx + cpx $3D + bne @4 + jsr routine31 + beq :+ + lda $C2 + cmp #$FD + bcc @4 +: jsr routine14 + bcc @1 + jsr routine29 +@1: jsr routine17 + bne W988B + bit print_color_flag + bpl @2 + inc $11 + lda $11 + cmp #$02 + bne W9883 + inc $10 + lda $10 + cmp #$07 + bne W987F +@2: jsr c1w_to_c3w + bit printer_type_flags + bpl @3 + ; Commodore MPS + jsr routine21 + bpl W986E + bmi W98E5 +@3: ; Epson/NEC P + lda $C4 + cmp #$FD + bcc W986E +W98E5: + jsr print_cr + bit print_color_flag + bpl :+ + ; Set printing colour to black + lda #'r' + jsr print_esc_char + lda #$00 ; Black + jsr BSOUT +: jmp print_done + +routine24: + inc $02 + lda $02 + cmp #200 + rts + +W9900: + sty $09 + jsr zero_48w +@1: jsr c3w_to_c1w + jsr zero_3ew + sty $02 + ldy $09 +: jsr routine13 + jsr routine14 + bcc :+ + jsr routine15 + jsr routine16 + jsr routine24 + bcc :- +: jsr routine38 + bcs :+ + lda $DC01 ; Data port B #1: keyboard, joystick, paddle + cmp #$7F + beq :+ + jsr routine30 + bne @1 + jsr routine17 + sty $09 + bne @1 +: jmp W534E + +routine6: + jsr routine20 + jsr routine40 + ldy #$00 + bit printer_type_flags + bpl :+ + bit print_color_flag + bmi W9900 +W994D: +: sty $09 + lda $03 + sta $05 + lda $06 + sta $07 + bit print_color_flag + bpl @4 + lda #$0A + jsr BSOUT + lda #$00 + sta $10 +@3: + lda #$00 + sta $11 +@4: + lda $10 + jsr routine32 + jsr c3w_to_c1w + jsr zero_3ew + sty $02 +@2: ldy $09 + lda $05 + sta $03 + lda $07 + sta $06 + jsr $54D4 +@1: jsr routine13 + jsr routine30 + bne :+ + jsr routine17 +: inx + cpx $3D + bne @1 + jsr routine31 + beq :+ + cpy #$A0 + bcc @1 +: jsr routine14 + bcc :+ + jsr routine29 +: jsr routine16 + jsr routine24 + bne @2 + bit print_color_flag + bpl :+ + inc $11 + lda $11 + cmp #$02 + bne @4 + inc $10 + lda $10 + cmp #$07 + bne @3 +: bit printer_type_flags + bpl :+ + jsr routine21 + bpl W994D + bmi W99D1 +: cpy #$A0 + bcs W99D1 + jmp W994D + +W99D1: + jmp W98E5 + +routine36: + ; $0B00 is VIC-II register backup. Weird code. + lda #$00 + ldx #$1A +: sta $0B30,x + dex + bpl :- + ldx #$03 +: sta $38,x + dex + bne :- + stx $38 + rts + +routine31: + bit print_color_flag + bmi W9A11 + bit $50 + bpl W9A0C + tya + pha + ldy #$00 + ldx $38 +: lda $0053,y + eor $25 + jsr routine18 + sta $0B30,x + inx + iny + cpy $29 + bne :- + pla + tay + jmp W9A1F + +W9A0C: + lda $9E + eor $25 + .byte $2c +W9A11: + lda $9E + jsr routine18 + pha + lda $38 + and #$03 + tax + pla + sta $39,x +W9A1F: + lda print_8p24p_flag + beq @x + ldx #$00 + lda $38 + clc + adc #$09 + sta $38 + cmp #$1B +@x: rts + +routine18: + bit printer_type_flags + bpl @x + stx $24 + ldx #7 + sta $9E +: lsr $9E + rol + dex + bne :- + and $46 + ora #$80 + ldx $24 +@x: rts + +routine29: + bit print_color_flag + bmi routine15 + bit $50 + bpl routine15 +@1: lda $0B2F,x + jsr BSOUT + bit print_8p24p_flag + bpl :+ + lda $0B38,x + jsr BSOUT + lda $0B41,x + jsr BSOUT +: dex + bne @1 + rts + +routine15: + lda $39 + jsr BSOUT + bit print_8p24p_flag + bpl :+ + lda $3A + jsr BSOUT + lda $3B + jsr BSOUT +: dex + bne routine15 + rts + +zero_3ew: + ldy #$00 + sty $3E + sty $3F + rts + +routine14: + lda $29 + sta $42 + bit printer_type_flags + bpl @1 + lda $40 + sec + sbc $3E + tax + lda $41 + sbc $3F + bcc @rts + pha + lda $3E + clc + adc $42 + sta $3E + bcc :+ + inc $3F +: pla + bne @1 + clc + txa + beq @rts + cpx $42 + bcc @2 +@1: ldx $42 +@2: sec +@rts: rts + +routine40: + ldy #$60 + lda #$7C + ora #$80 + bne :+ +routine39: + ldy #$00 + lda #$80 +: sty $C3 + sta $C4 + ldx #$00 + stx $02 + stx $03 + stx $05 + stx $06 + dex + stx $04 + rts + + lda $AF + jsr W9AE3 + sta $AF + lda $AE + jsr W9AE3 + sta $AE + lda $9E +W9AE3: + bit printer_type_flags + bpl reverse_bits_A + lsr + and $04 + ora #$80 + rts + +reverse_bits_A: + pla + sta $FD + ldx #8 +: lsr $FD + rol + dex + bne :- + rts + +routine37: + inc $06 + lda $06 + cmp print_vertical_size + bcc :+ + lda #$00 + sta $06 +: rts + +routine30: + inc $06 + lda $06 + cmp print_horizontal_size + bcc :+ + lda #$00 + sta $06 +: rts + + bit $50 + bmi W9B1F + +routine17: + lda $03 + eor #$10 + sta $03 + bne W9B20 +W9B1F: + iny +W9B20: + cpy #$A0 + rts + +W9B23: + tax + lda tabel2,x + sta $39 + rts + +tabel2: + .byte $00,$01,$04,$03,$04,$05,$06,$07 + .byte $02,$02,$02,$00,$01,$05,$03,$01 + +W9B3A: + bit printer_type_flags + bmi W9B23 + ldx $11 + beq @1 + tax + lda tabel3,x + cmp $10 + sec + bcs @2 +@1: tax + lda tabel3+$10,x + cmp $10 + sec +@2: beq :+ + clc +: rol $9E + rts + +tabel3: + .byte $00, $10, $01, $02, $01, $06, $02, $04 + .byte $05, $01, $01, $10, $10, $06, $02, $10 + .byte $10, $10, $01, $10, $02, $06, $02, $10 + .byte $10, $00, $10, $10, $10, $10, $10, $10 + + +routine13: + sei + lda #$34 ; Disable ROM + sta $01 + tya + pha + txa + pha + lda $03 + cmp #$10 + lda ($C1),y + bcc :+ + lsr + lsr + lsr + lsr +: and #$0F + jsr routine25 + lda #$37 ; Enable ROM + sta $01 + pla + tax + pla + tay + cli + rts + +routine25: + bit print_color_flag + bmi W9B3A + bit $50 + bpl W9BEB + pha + lda #$00 + sta $48 + lda #$60 + sta $49 + lda $03 + beq :+ + lda $48 + clc + adc $51 + sta $48 + lda $49 + adc $52 + sta $49 +: ldx $06 + beq @3 +@1: lda $48 + clc + adc $27 + sta $48 + bcc :+ + inc $49 +: dex + bne @1 +@3: pla + tay + ldx $29 +@2: lda ($48),y + clc + beq :+ + sec +: rol $52,x + lda $48 + clc + adc $28 + sta $48 + bcc :+ + inc $49 +: dex + bne @2 + rts + +W9BEB: + bit $26 + bpl @3 + sta $51 + lda #$00 + sta $48 + lda #$40 + sta $49 +@1: sec + sbc #$05 + bcc @2 + pha + clc + lda $48 + adc #$28 + sta $48 + bcc :+ + inc $49 +: pla + jmp @1 +@2: tya + lsr + lsr + tay + lda ($48),y + and #$0F + cmp $51 + clc + bcc @4 +@3: cmp $0B21 + clc +@4: beq :+ + sec +: rol $9E + rts + + +c1w_to_c3w: + lda $C1 + sta $C3 + lda $C2 + sta $C4 + rts + +c3w_to_c1w: + lda $C3 + sta $C1 + lda $C4 + sta $C2 + rts + +routine23: + lda $C1 + clc + adc #$A0 + sta $C1 + bcc :+ + inc $C2 +: rts + +routine16: + lda $C1 + sec + sbc #$A0 + sta $C1 + bcs :+ + dec $C2 +: rts + +routine20: + jsr routine34 + bcs except_close_all + bit printer_type_flags + bmi W9C7D ; CBM printer + bvc W9C69 + lda #$1C + jsr BSOUT + lda #'3' + jsr BSOUT + lda #'/' + jmp BSOUT + +W9C69: + lda #'3' ; Set line spacing + jsr print_esc_char + lda #23 ; 23/180 inch + jsr BSOUT + lda #'A' ; Set line spacing + jsr print_esc_char + lda #$08 ; 8/60 inch + jmp BSOUT +W9C7D: + bit print_color_flag + bmi maybe_set_size + lda #$08 ; 8/60 inch (or enter graphics mode when called via label for CBM printers) +jmp_bsout: + jmp BSOUT + +print_cr: + lda #$0D + bne jmp_bsout +except_close_all: + pla + pla + jmp close_all + +maybe_set_size: + ; This ESC 'C' command is supported by the CBM MCS-801 and is used for + ; "scan mode bit image printing". + ; + ; On the MCS-820 and MPS-1550C ESC 'C sets the page length like Epson. + lda #'C' + jsr print_esc_char ; + bit print_sideways_flag + bpl :+ + jsr routine26 + jmp routine19 +: jsr routine19 + +routine26: + lda print_vertical_size + ldx #'2' + ldy #'0' + cmp #$01 + beq out_2c0 ;'200' + ldx #'4' + cmp #$02 + beq out_2c0 ;'400' + ldx #'6' + cmp #$03 + beq out_2c0 ;'600' + ldy #'4' ;'640' + bne out_2c0 + +routine19: + lda print_horizontal_size + ldx #'3' + ldy #'2' + cmp #$01 + beq out_2c0 + ldx #'6' + ldy #'4' +out_2c0: + txa + jsr BSOUT + tya + jsr BSOUT + lda #'0' + jmp BSOUT + +print_esc_char: + pha + lda #$1B + jsr BSOUT + pla + bne jmp_bsout + +routine32: + bit print_color_flag + bpl :+ + ; Set printing colour to A + pha + lda #'r' + jsr print_esc_char + pla + jsr BSOUT +: lda $DC01 + cmp #$7F ; Check for run/stop + beq print_abort + jsr print_cr + bit printer_type_flags + bmi W5855 + lda print_graphmode_val + cmp #$04 + bcs W581F + lda $DC0C + beq :+ + cmp #'7' + bcs :+ + cmp #'0' + bcs W581F +: lda print_graphmode_val + cmp #$02 + bcs :+ + adc #$4B + .byte $2C ; Skip next instruction +: adc #$56 + jsr print_esc_char + jmp W5829 + +W581F: + lda #'*' + jsr print_esc_char + lda print_graphmode_val + jsr BSOUT +W5829: + lda $33 + jsr BSOUT + lda $34 + jmp BSOUT + +print_abort: + pla + pla +print_done: + jsr print_cr + bit printer_type_flags + bmi @mps + bit print_color_flag + bpl close_all + ; Set colour to black + lda #'r' + jsr print_esc_char + lda #$00 + .byte $2C ; Skip next instruction +@mps: lda #$0F ; Exit graphics mode, single width text printing + jsr BSOUT +close_all: + jsr CLALL + lda #$01 + jsr CLOSE +W5855: + rts + +routine34: + lda #$01 + ldy #$01 + bit printer_type_flags + bpl :+ + dey +routine22: +: ldx #4 ; Device 4 = printer + jsr SETLFS + + lda #0 + jsr SETNAM + jsr OPEN + ldx #1 + jmp CKOUT + +printer_graphmodes: + .byte $00, $01, $02, $03, $04, $06, $20, $21 + .byte $26, $27 + +tabel4: + .byte $10, $00, $0B, $03, $09, $05 + .byte $0D, $01, $0A, $0E, $06, $0C, $07, $02 + .byte $08, $04 + +end_of_text: + +.segment "printersettings" + +; AE000 +.global freezer_screenshot_prepare +freezer_screenshot_prepare: + ldx #<__copycode_SIZE__ - 1 +: lda __copycode_LOAD__,x + sta <__copycode_RUN__,x ; DATA current line number + dex + bpl :- + ldy #$00 + ; Compute VIC-II base adress + lda $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + and #$03 + eor #$03 + sta $C8 + lsr + ror + ror + sta $AD + ldx #>$4000 + stx $AF + ; Copy the VIC-II bank to $4000..$7FFF + lda #$34 + jsr copy_x_pages + + + lda $D011 + and #$20 ; Charset not needed in bitmap mode + bne @1 + lda $C8 + bne @1 ; Charset only needed in bank 0?? Wrong! :) + lda $D018 ; VIC memory control register + and #$0E + cmp #$04 ; Charset at $1000 + beq :+ + cmp #$06 ; Or $1800? + bne @1 +: ; Copy the character ROM to $5000. + lda #>$D000 + sta $AD + lda #>$5000 + sta $AF + ldx #$10 + lda #$33 + jsr __copycode_LOAD__ ; Ugly! + +@1: ; Copy the colour RAM to $1800 + lda #>$D800 + sta $AD + lda #>$1800 + sta $AF + ldx #$04 + lda #$37 + jsr __copycode_LOAD__ ; Ugly! + ; Y=0 + + ; Backup the VIC-II to $0B00 +: lda $D000,y + sta $0B00,y + iny + bne :- + + lda $0B11 + and #$20 + sta $C7 ; bitmap mode flag + lda $0B16 + and #$10 + asl + sta $AC ; 40 column flag + + ldx #$00 + stx $C1 + stx $C3 + stx $CE ; Character line counter + + lda $0B18 + tax + and #$F0 + lsr + lsr + ora #$40 + sta $C2 ; ($C1) = pointer to screen RAM + + txa + and #$08 + ora #$10 + lsr + ldy $C7 + bne :+ + txa + and #$0E + ora #$10 + lsr +: sta $C8 ; $10|bitmap / $10|charset + + lda #>$1800 ; colour RAM pointer + sta $C4 + lda $0B23 ; background colour 2 + sta $B4 + lda $0B22 ; background colour 1 + sta $B5 + lda #$00 + sta $B2 + lda #$80 + sta $B3 + lda #>$1900 + sta $CD + + ; VIC-II bank to $4000..$7FFF + lda $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + and #$FC + ora #$02 + sta $DD00 ; Data port A #2: serial bus, RS-232, VIC memory + + lda #$33 + sta $01 + bne @4 ; Always! + +@2: lda #$00 + sta $CE ; Character line counter + lda $C1 + clc + adc #40 ; Move one line down + sta $C1 + sta $C3 + bcc @4 + inc $C2 + inc $C4 + lda $C7 + beq @4 + inc $C8 +@4: lda #$00 + sta $CF +@3: lda $C8 ; Copy charset location + sta $CA + ldy $CF + lda ($C3),y + ldx $C7 + bne :+ + ldx $AC + beq :+ + and #$07 + tax + lda ($C3),y + and #$08 + sta $03 + txa +: and #$0F + sta $B6 + jsr read_pixel_byte + lda #$80 + sta $AE + jsr WA234 + inc $CF + lda $CF + cmp #40 + bcc @3 + inc $CE + lda $CE + cmp #$08 + bne @4 + dec $CD + bne @2 + jsr WA27D + lda #$37 + sta $01 ; 6510 I/O register + ldx #$FF + sei + txs + cld + jsr $FDA3 ; IOINIT inside KERNAL + lda #$00 + tay +: sta $0002,y + sta $0200,y + sta $0300,y + iny + bne :- + jsr $FD15 ; Routine RESTOR of KERNAL + ldx #$00 + ldy #$A0 + jsr $FE2D ; SETTOP inside KERNAL + lda #$08 + sta $0282 ; Pointer: Memory base for Operative System + lda #$04 + sta $0288 ; Top of memory screen (page) + jsr $FF5B ; Routine CINT of KERNAL + jsr $E453 ; Routine: Set BASIC vectors (case 0x300..case 0x309) + jsr $E3BF ; Routine: Set USR instruction and memory for BASIC + + ; Backup $C000..$CFFF to $0C00 + ldy #$00 + sty $AC + sty $AE + lda #>$C000 + sta $AD + lda #>$0C00 + sta $AF + ldx #$10 +: lda ($AC),y + sta ($AE),y + iny + bne :- + inc $AD + inc $AF + dex + bne :- + + ; Copy the screenshot code to $5000 + lda #>__screenshotcode_LOAD__ + sta $AD + lda #>__screenshotcode_RUN__ + sta $AF + ldx #(>__screenshotcode_SIZE__) + 2 ; copy one page too much +: lda ($AC),y + sta ($AE),y + iny + bne :- + inc $AD + inc $AF + dex + bne :- + + ; Copy the screen RAM to $4000 + lda $0B18 ; Backup of $D018 + and #$F0 + lsr + lsr + clc + adc #$40 + sta $AD + lda #>$4000 + sta $AF + ldy #<$4000 + sty $AC + sty $AE + + ldx #$04 +: lda ($AC),y + sta ($AE),y + iny + bne :- + inc $AD + inc $AF + dex + bne :- + + lda #>$8017 ; init_vectors_goto_psettings + pha + lda #<$8017 + pha + jmp _enable_fcbank0 + +WA1BA: + lda $AC + bne @5 + lda $C7 + bne @3 +@1: lda $B0 + and $AE + bne @2 + lda $0B21 ; Backup of $D021 + .byte $2c ; Skip next instruction +@2: lda $B6 + rts +@3: lda $B0 + and $AE + bne @4 + lda $B4 + rts +@4: lda $B5 + rts +@5: lda $C7 + bne @6 + lda $03 + beq @1 +@6: jsr WA1E9 + asl $AE + rts + +WA1E9: + lda $B0 + tax + and $AE + bne @2 + lsr $AE + txa + and $AE + beq @1 + lda $B5 + rts +@1: lda $0B21 + rts +@2: lsr $AE + txa + and $AE + beq @3 + lda $B6 + rts +@3: lda $B4 + rts + +; +; $A20B +; +read_pixel_byte: + lda ($C1),y ; Get byte from screen RAM + ldx $C7 + beq :+ ; Text mode? Jump + ; Bitmap mode... byte contains colours + sta $B4 ; Background colour + lsr + lsr + lsr + lsr + sta $B5 ; Foreground colour + tya + clc + adc $C1 + bcc :+ + inc $CA +: ldx #3 +: asl + rol $CA + dex + bne :- + ora $CE ; Character scan line + sta $C9 + ldy #$00 + lda ($C9),y ; Read a byte from character ROM or the bitmap + sta $B0 + rts + +WA234: + jsr WA1BA + and #$0F + pha + lsr $AE + ldx $AC + beq @2 + ldx $C7 + bne @1 + ldx $03 + beq @2 +@1: lsr $AE + pha +@2: bcc WA234 + ldy #3 +: pla + asl + asl + asl + asl + sta $02 + pla + ora $02 + sta ($B2),y + dey + bpl :- + lda $B2 + clc + adc #$04 + sta $B2 + bcc :+ + inc $B3 + lda $B3 + and #$0F + bne :+ + lda $01 + pha + lda #$37 + sta $01 + inc $D020 ; Border color + pla + sta $01 +: rts + +WA27D: + lda #$80 + sta $02 + lda #$07 + sta $03 + lda #$F8 + sta $C1 + ldx #<__ramload_SIZE__ -1 +: lda __ramload_LOAD__,x + sta <__ramload_RUN__,x + dex + bpl :- +@5: lda $0B15 + and $02 + beq @4 + lda $0B1B + and $02 + bne @4 + jsr WA2FB + lda #$00 + sta $33 +@2: jsr WE363 + lda $08 + cmp #$C8 + bcs @3 + jsr WA3AB + lda $06 + sta $30 + lda $07 + sta $31 + lda #$00 + sta $32 +@1: lda $31 + beq :+ + lda $30 + cmp #$40 + bcs @6 +: lda $32 + ldy $0B + cpy #$18 + beq :+ + lsr +: tay + lda $0040,y + beq @6 + jsr stuff37a_to_lhnibble_of_3e +@6: inc $30 + bne :+ + inc $31 +: inc $32 + lda $32 + cmp $0B + bcc @1 +@3: inc $08 + inc $33 + lda $33 + cmp $0A + bcc @2 +@4: lsr $02 + dec $03 + bpl @5 + rts + +WA2FB: + lda #$01 + sta $05 + ldx #$06 + ldy $03 + lda ($C1),y +: asl + rol $05 + dex + bne :- + sta $04 + lda $03 + asl + tay + sec + lda $0B01,y + sbc #$32 + sta $08 + sec + lda $0B00,y + sbc #$18 + sta $06 + ldx #$00 + lda $0B10 + and $02 + beq :+ + inx +: txa + sbc #$00 + sta $07 + lda $0B1C + and $02 + sta $09 + ldx #$15 + lda $0B17 ; Backup of $D017 + and $02 + beq :+ + ldx #$2A +: stx $0A + ldx #$18 + lda $0B1D ; Backup of $D01D + and $02 + beq :+ + ldx #$30 +: stx $0B + lda $0B25 ; Backup of $D025 + sta $38 + ldy $03 + lda $0B27,y + sta $39 + lda $0B26 + sta $3A + rts + +WE363: + lda $33 + ldx $0A + cpx #$15 + beq :+ + lsr + bcs @rts +: ldy #$00 +: lda ($04),y + sta $000C,y + iny + cpy #$03 + bne :- + tya + clc + adc $04 + sta $04 + bcc :+ + inc $05 +: ldx #$00 +@1: asl $0E + rol $0D + rol $0C + lda #$00 + bcc :+ + lda #$02 +: ldy $09 + bne @2 +@3: sta $40,x + inx + cpx #$18 + bne @1 +@rts: rts + +@2: asl $0E + rol $0D + rol $0C + adc #$00 + sta $40,x + inx + bne @3 + +WA3AB: + lda #<$8000 + sta $3E + lda #>$8000 + sta $3F + ldy $08 + beq @rts +@1: clc + lda $3E + adc #$A0 + sta $3E + bcc :+ + inc $3F +: dey + bne @1 +@rts: rts + +stuff37a_to_lhnibble_of_3e: + tax + lda $37,x + and #$0F + tax + lda $31 + lsr + lda $30 + ror + tay + jsr load_3e_rom_hidden ; preserves C + bcs WE3E2 + and #$F0 + sta $3C + txa + ora $3C +WE3DF: + sta ($3E),y + rts + +WE3E2: + and #$0F + sta $3C + txa + asl + asl + asl + asl + ora $3C + jmp WE3DF + + +.segment "ramload" + +load_3e_rom_hidden: + lda #$34 + sta $01 + lda ($3E),y + dec $01 + rts + +.segment "copycode" + +copy_x_pages: + sta $01 +copy_ac_ec: + sty $AC + sty $AE +: lda ($AC),y + sta ($AE),y + iny + bne :- + inc $AD + inc $AF + dex + bne :- + lda #$37 + sta $01 + rts + diff --git a/bank3/tape_backload/Makefile b/bank3/tape_backload/Makefile new file mode 100644 index 0000000..5777388 --- /dev/null +++ b/bank3/tape_backload/Makefile @@ -0,0 +1,13 @@ +all: backup_loader.prg + +basic_stub.bin: basic_stub.bas + petcat -w2 -l 0x0801 -o $@ $< + +backup_loader.o: backup_loader.s basic_stub.bin + ca65 --target c64 -l backup_loader.lst -o $@ $< + +backup_loader.prg: backup_loader.o + cl65 -m backup_loader.map -C backup_loader.cfg -o $@ $< + +clean: + rm -f *.o *.bin *.prg *.hexdump *.lst *.map diff --git a/bank3/tape_backload/backup_loader.cfg b/bank3/tape_backload/backup_loader.cfg new file mode 100644 index 0000000..5e0f28a --- /dev/null +++ b/bank3/tape_backload/backup_loader.cfg @@ -0,0 +1,24 @@ +MEMORY { + BASICSTUB: + file = %O, + fill = yes, + fillval = $ff, + start = %S - $0801, + size = 14; + MAIN: + file = %O, + start = $080D, + size = $2000, + define = yes; + LOW: + file="", + fill=no, + start=$0200, + size=$0200; +} + +SEGMENTS { + BASIC_STUB: load = BASICSTUB, type = ro; + CODE: load=MAIN, type=ro; + LOWCODE: load=MAIN, run=LOW, type=rw, define=yes; +} diff --git a/bank3/tape_backload/backup_loader.s b/bank3/tape_backload/backup_loader.s new file mode 100644 index 0000000..484937b --- /dev/null +++ b/bank3/tape_backload/backup_loader.s @@ -0,0 +1,359 @@ +.import __LOWCODE_LOAD__ +.import __MAIN_LAST__ + +; +; This is the loader that loads and continues a Final Cartridge III tape +; backup. After the loader, a file is stored on tape that stores the +; memory contents from $0403 to $fffd. This file is RLE compressed and +; needs decompression. +; +; Zeropage, stack, $0200..0403 and colour RAM is included in the loader +; and starts right after code end. +; + +.zeropage +zp_loaded_byte := $90 +zp_bit_counter := $91 +zp_load_0200_addr := $92 +zp_decompress_dst := $91 +zp_decompress_src := $96 + +.segment "BASIC_STUB" + +.incbin "basic_stub.bin" + +.segment "CODE" + +stored_zeropage = __MAIN_LAST__ + $0000 +stored_stack = __MAIN_LAST__ + $0100 +stored_colram = __MAIN_LAST__ + $0200 +stored_vicregs = __MAIN_LAST__ + $0600 +stored_0400 = __MAIN_LAST__ + $062f + +nr_vicregs = $2f + +start: + sei + lda #$7F + sta $DC0D ; Interrupt control register CIA #1 + sta $DD0D ; Interrupt control register CIA #2 + ; Initialize all SID voices + ldx #14 ; Start with voice 3, iterate down +: lda #$80 + sta $D402,x ; Pulse width low byte + sta $D403,x ; Pulse width high byte + lda #$21 ; Sawtooth + voice on + sta $D404,x ; Voice control register + lda #$08 + sta $D405,x ; Attack/Decay + lda #$80 + sta $D406,x ; Sustain/Release + txa + sec + sbc #$07 ; Subtract 7 for next voice + tax + bpl :- + lda #$8F + sta $D418 ; Select volume and filter mode + ldx #$00 + stx $DC0E ; Control register A of CIA #1 + ; + ; Note that the freezer, upon entry, searches for two memory areas: + ; one contains a backup of $0070..$00d6, the other the "restore" + ; routine. + ; + ; The loader restores the memory in this state, i.e. after loading + ; memory, $0070..$00d6 still can be used by the loader, and the restore + ; routine is loaded from backup as well. It can ultimately do an rts to + ; activate the restore routine that restores both memory areas and + ; returns control to the program. + +@1: ; Restore the zero page + lda stored_zeropage,x + sta $00,x + ; Restore the stack + lda stored_stack,x + sta $0100,x + ; Restore the colour ram + lda stored_colram+$0000,x + sta $D800,x + lda stored_colram+$0100,x + sta $D900,x + lda stored_colram+$0200,x + sta $DA00,x + lda stored_colram+$0300,x + sta $DB00,x + ; Install the low code that will load the rest of the backup + lda __LOWCODE_LOAD__+$0000,x + sta $0200,x + lda __LOWCODE_LOAD__+$0100,x + sta $0300,x + cpx #$03 + bcs :+ + lda stored_0400,x + sta $0400,x +: inx + bne @1 + ldx #nr_vicregs-1 +: lda stored_vicregs,x + sta $D000,x ; Position X sprite 0 + dex + bpl :- + ldx $93 ; $93 contains the backed up stack pointer + txs + lda #$35 ; Only I/O + sta $01 ; 6510 I/O register + jmp lowcode_entry + +.segment "LOWCODE" + +.proc tape_load_byte_fast + lda #8 ; Load 8 bits +bc1: sta $A3 ; Bit counter +n: jsr tape_load_bit_fast + rol z:zp_loaded_byte ; Rol bit into z:zp_loaded_byte +bc2: dec $A3 ; Decrease bit counter + bne n + lda z:zp_loaded_byte ; Return loaded byte in A + rts +.endproc + +.proc tape_load_bit_fast + lda #$10 ; Wait until flag bit +: bit $DC0D ; Interrupt control register CIA #1 + beq :- + lda $DD0D ; Interrupt control register CIA #2 + stx $DD07 ; Timer B #2: HI Byte + pha + lda #$19 ; Start timer B + sta $DD0F ; Control register B of CIA #2 + pla + lsr ; Bit 1 (timer B underflow) to C + lsr + rts +.endproc + +lowcode_entry: + jsr tape_prepare + jsr tape_read_turbotape_header + ; Load 4 bytes: +: jsr tape_load_byte_fast + sta $0397,y ; Tape I/O buffer + iny + cpy #$03 + bne :- + + ; Get the load address at $91/$92 and patch code below + jsr tape_load_byte_fast + sta zp_decompress_dst + sta @load_loadaddr_low+1 + jsr tape_load_byte_fast + sta zp_decompress_dst+1 + sta @load_loadaddr_high+1 + + ; Load the backup in memory + ldy #0 +: jsr tape_load_byte_fast + dec $01 ; Hide I/O + sta (zp_decompress_dst),y + inc $01 ; Enable I/O + inc z:zp_decompress_dst + bne :- + inc z:zp_decompress_dst+1 ; Constant (timeout) of time misure for tape + bne :- + + ; Decompress the backup + lda #$1B ; Enable the screen + sta $D011 ; VIC control register + lda #$34 ; Back to normal memory layout + sta $01 ; 6510 I/O register +@load_loadaddr_low: + lda #$FF + sta $96 +@load_loadaddr_high: + lda #$FF + sta $97 + ; Decompressed data written to addresses starting at $0403 + lda #<$0403 + sta zp_decompress_dst ; Flag: key STOP/ key RVS + lda #>$0403 + sta zp_decompress_dst+1 ; Constant (timeout) of time misure for tape + ldy #0 + ldx #0 +@8: lda ($96),y ; Number (EOT) of cassette sincronism + bne @1 + jsr load_next_byte + tax +@2: jsr load_next_byte + jsr store_next_byte + dex +@3: bne @2 +@6: jsr load_next_byte + lda $91 + cmp #<$FFFD + lda $92 + sbc #>$FFFD + bcc @8 + bcs done_decompress +@1: tax + dex + bne @4 + jsr load_next_byte + pha + jsr load_next_byte + sta z:zp_loaded_byte ; Store number of bytes into z:zp_loaded_byte +: jsr load_next_byte + jsr store_next_byte + inx + bne :- + dec z:zp_loaded_byte ; Decrease counter + bne :- + pla + tax + sec + bcs @3 +@4: dex + beq @7 + inx + inx + jsr load_next_byte +: jsr store_next_byte + dex +@5: bne :- + beq @6 ; Always + +@7: jsr load_next_byte + pha + jsr load_next_byte + sta z:zp_loaded_byte + jsr load_next_byte +: jsr store_next_byte + inx + bne :- + dec z:zp_loaded_byte + bne :- + sta z:zp_loaded_byte + pla + tax + lda z:zp_loaded_byte + cpx #0 + sec + bcs @5 ; Always + +.proc load_next_byte + inc z:zp_decompress_src + bne :+ + inc z:zp_decompress_src+1 +: lda (zp_decompress_src),y + rts +.endproc + +.proc store_next_byte + sta (zp_decompress_dst),y + inc z:zp_decompress_dst + bne :+ + inc z:zp_decompress_dst+1 +: rts +.endproc + +done_decompress: + ; Restore vectors +: lda $0397,y ; Tape I/O buffer + sta $FFFD,y + iny + cpy #$03 + bne :- + lda #$35 + sta $01 + ; Store the load_0200 code in the zero page + ldx #load_0200_size - 1 +: lda load_0200,x + sta z:zp_load_0200_addr,x + dex + bpl :- + jsr tape_prepare + ; We will jump to load_0200 (in zeropage) via rts, so push adress + lda #$00 + pha + lda #zp_load_0200_addr -1 + pha + lda #$91 + sta tape_load_byte_fast::bc1+1 + sta tape_load_byte_fast::bc2+1 + jsr tape_read_turbotape_header + jsr zp_load_0200_addr ; Load data in $0200 + inc z:patch_0200_0300_loc + rts ; Load data in $0300 + ; When load_0200 returns, this will continue the backed up program + +.proc tape_read_turbotape_header + ; + ; A turbotape header starts with a pilot tone of a large amount of $02 bytes + ; in order to allow synchronization, then $09,$08,$07,$06,$05,$04,$03,$02,$01 + ; to allow a check wether it is a valid header. + ; + lda #$07 + sta $DD06 ; Timer B #2: Lo Byte + ldx #$01 +@1: jsr tape_load_bit_fast + rol z:zp_loaded_byte ; Shift into z:zp_loaded_byte + lda z:zp_loaded_byte + cmp #$02 ; If we have $02 it might be a pilot tone. + bne @1 + ldy #$09 ; Count down from 9 +: jsr tape_load_byte_fast + cmp #$02 ; Skip any remaining bytes of the pilot tone + beq :- +: cpy z:zp_loaded_byte ; Equal to counter + bne @1 ; No? Then it wasn't a header + jsr tape_load_byte_fast ; Load next byte + dey + bne :- + rts +.endproc + +.proc tape_prepare + ; Wait for play on tape + lda #$10 ; Cassette sense bit +: bit $01 ; Cassette sense? + bne :- ; No, then loop + lda $01 ; 6510 I/O register + and #$07 ; Switch on tape motor + sta $01 ; 6510 I/O register + ldy #$00 + lda #$0B ; Disable screen + sta $D011 ; VIC control register +: dex ; Delay loop to wait until bad lines gone + bne :- + dey + bne :- + sei + rts +.endproc + +.proc load_0200 +s: lda #$08 + sta z:zp_bit_counter +n: lda #$10 +: bit $DC0D ; Interrupt control register CIA #1 + beq :- + lda $DD0D ; Interrupt control register CIA #2 + stx $DD07 ; Timer B #2: HI Byte + pha + lda #$19 ; Start timer B + sta $DD0F ; Control register B of CIA #2 + pla + lsr ; Bit 1 (timer B underflow) to C + lsr + rol z:zp_loaded_byte + dec z:zp_bit_counter + bne n + lda z:zp_loaded_byte +wrt: sta $0200,y + iny + bne s + rts +.endproc + +load_0200_size = .sizeof(load_0200) +patch_0200_0300_loc := zp_load_0200_addr + (load_0200::wrt + 2 - load_0200) diff --git a/bank3/tape_backload/basic_stub.bas b/bank3/tape_backload/basic_stub.bas new file mode 100644 index 0000000..e1912c7 --- /dev/null +++ b/bank3/tape_backload/basic_stub.bas @@ -0,0 +1 @@ +1986 sys2061 diff --git a/core/fc3ioreg.i b/core/fc3ioreg.i new file mode 100644 index 0000000..f7c7ac2 --- /dev/null +++ b/core/fc3ioreg.i @@ -0,0 +1,14 @@ +fcio_bank_0 := $00 +fcio_bank_1 := $01 +fcio_bank_2 := $02 +fcio_bank_3 := $03 +fcio_unassigned_bit2 := $04 +fcio_unassigned_bit3 := $08 +fcio_c64_16kcrtmode := $00 ; FC3 rom at $8000..$bfff +fcio_c64_ultimaxmode := $10 ; Starts freezer +fcio_c64_8kcrtmode := $20 ; FC3 rom at $8000..$9fff +fcio_c64_crtrom_off := $30 ; only io1/io2 active +fcio_nmi_line := $40 ; 0 = generate nmi +fcio_kill := $80 ; 1 = disable FC3 hardware + +fcio_reg := $DFFF ; Final Cartridge III io register diff --git a/core/kernal_c64.i b/core/kernal_c64.i index 5c590ee..ffdbcb4 100644 --- a/core/kernal_c64.i +++ b/core/kernal_c64.i @@ -9,9 +9,16 @@ LF0BD := $F0BD ; string "I/O ERROR" LF333 := $F333 ; default contents of CLRCHN vector LF646 := $F646 ; IEC close +PRT := $E716 +IOINIT_direct := $FDA3 +RESTOR_direct := $FD15 +CINT_direct := $FF5B + ICLRCH := $0322 ; CLRCHN vector IBSOUT := $0326 ; CHROUT vector +START := $FCE2 ; RESET routine + R6510 := $01 ; 6510 I/O register TXTPTR := $7A ; current byte of BASIC text ST := $90 ; kernal I/O status diff --git a/core/persistent.s b/core/persistent.s deleted file mode 100644 index 0d3b636..0000000 --- a/core/persistent.s +++ /dev/null @@ -1,397 +0,0 @@ -; ---------------------------------------------------------------- -; I/O Area ROM -; ---------------------------------------------------------------- -; This is a max. 512 byte section that lives at $1E00-$1FFF of -; bank 0 of the ROM, and will also be mapped into the I/O extension -; area at $DE00-$DFFF, so it's always visible. -; It mostly contains wrappers around BASIC, KERNAL or cartridge -; functions that switch the ROM config in addition. - -.include "kernal.i" - -; from printer -.import new_clrch -.import new_clall -.import new_bsout -.import new_ckout - -; from basic -.import reset_warmstart -.import new_tokenize -.import new_execute -.import new_expression -.import new_detokenize -.import new_mainloop - -; from editor -.import kbd_handler - -; from wrapper -.import disable_rom_then_warm_start - -; from speeder -.import new_save -.import new_load - -; from desktop_helper -.import load_and_run_program - -.segment "romio" - -LDE00: .byte $40 - -.global _jmp_bank -_jmp_bank: - sta $DFFF - rts - -.global _enable_rom -_enable_rom: ; $DE05 - pha - lda #$40 ; bank 0 -LDE08: sta $DFFF - pla - rts - -.global _disable_rom_set_01 -_disable_rom_set_01:; $DE0D - sty $01 -.global _disable_rom -_disable_rom: ; $DE0F - pha - lda #$70 ; no ROM at $8000; BASIC at $A000 - bne LDE08 - -.global _basic_warm_start -_basic_warm_start: ; $DE14 - jsr _disable_rom - jmp $E37B ; BASIC warm start (NMI) - -enable_all_roms: - ora #$07 - sta $01 - bne _enable_rom - -.global _new_load -_new_load: ; $DE20 - tay - tay ; XXX - lda $01 - pha - jsr enable_all_roms - jsr new_load -LDE2B: tax - pla - sta $01 - txa - ldx $AE - jmp _disable_rom - -.global _new_save -_new_save: ; $DE35 - lda $01 - pha - jsr enable_all_roms - jsr new_save - jmp LDE2B - -.global _new_mainloop -_new_mainloop: ; $DE41 - lda $01 - jsr enable_all_roms - jmp new_mainloop - -.global _new_detokenize -_new_detokenize: ; $DE49 - jsr _enable_rom - jmp new_detokenize - -.global _new_expression -_new_expression: ; $DE4F - jsr _enable_rom - jmp new_expression - -.global _kbd_handler -_kbd_handler: - lda $02A7 - beq LDE5D - jmp $EB42 ; LDA #$7F : STA $DC00 : RTS - -LDE5D: lda $A000 - jmp LDF80 - -.global _load_ac_indy -_load_ac_indy: ; $DE63 - sta $01 - lda ($AC),y - inc $01 - inc $01 - rts - -.global _load_FNADR_indy -_load_FNADR_indy: ; $DE6C - dec $01 - lda (FNADR),y - inc $01 - rts - -.global _new_execute -_new_execute: ; $DE73 - jsr _CHRGET - jsr new_execute - jsr _disable_rom - jmp $A7AE ; CLEAR - -.global _execute_statement -_execute_statement: ; $DE7F - jsr _disable_rom - jmp $A7EF ; execute BASIC statement - -.global _add_A_to_FAC -_add_A_to_FAC: ; $DE85 - jsr _disable_rom - jsr $BD7E ; add A to FAC - jmp _enable_rom - -.global _expression_cont -_expression_cont: ; $DE8E - jsr _disable_rom - jmp $AE8D ; get element in expression - -.global _get_int -_get_int: ; $DE94 - jsr _disable_rom - jsr $AD8A ; FRMNUM eval expression, make sure it's numeric - jsr $B7F7 ; GETADR convert FAC into 16 bit int - jmp _enable_rom - -.global _new_warmstart -_new_warmstart: - jsr _enable_rom - jsr reset_warmstart - jmp disable_rom_then_warm_start - -.global _evaluate_modifier -_evaluate_modifier: ; $DEA9 - jsr _disable_rom - jmp $EB48 ; evaluate SHIFT/CTRL/C= - -.global _get_line_number -_get_line_number: ; $DEAF - jsr _disable_rom - jsr $A96B ; get line number - jmp _enable_rom - -.global _basic_bsout -_basic_bsout: ; $DEB8 - jsr _disable_rom - jsr $AB47 ; print character - jmp _enable_rom - -.global _set_txtptr_to_start -_set_txtptr_to_start: ; $DEC1 - jsr _disable_rom - jsr $A68E ; set TXTPTR to start of program - jmp _enable_rom - -.global _check_for_stop -_check_for_stop: ; $DECA - jsr _disable_rom - jsr $A82C ; check for STOP - jmp _enable_rom - -.global _relink -_relink: ; $DED3 - jsr _disable_rom - jsr $A533 ; rebuild BASIC line chaining - beq LDEE1 ; branch always? - -.global _get_filename -_get_filename: ; $DEDB - jsr _disable_rom - jsr $E257 ; get string from BASIC line, set filename -LDEE1: jmp _enable_rom - -.global _int_to_ascii -_int_to_ascii: ; $DEE4 - jsr _disable_rom - jsr $BC49 ; FLOAT UNSIGNED VALUE IN FAC+1,2 - jsr $BDDD ; convert FAC to ASCII - jmp _enable_rom - -.global _ay_to_float -_ay_to_float: ; $DEF0 - jsr _disable_rom - jsr $B395 ; convert A/Y to float - jmp LDEFF - -.global _int_to_fac -_int_to_fac: ; $DEF9 - jsr _disable_rom - jsr $BBA6 ; convert $22/$23 to FAC -LDEFF: iny - jsr $BDD7 ; print FAC - jmp _enable_rom - - -.global _print_ax_int -_print_ax_int: ; $DF06 - jsr _disable_rom - jsr $BDCD ; LINPRT print A/X as integer - jmp _enable_rom - -.global _search_for_line -_search_for_line: ; $DF0F - jsr _disable_rom - jsr $A613 ; search for BASIC line - php - jsr _enable_rom - plp - rts - -.global _CHRGET -_CHRGET: ; $DF1B - jsr _disable_rom - jsr CHRGET -LDF21: php - jsr _enable_rom - plp - rts - -.global _CHRGOT -_CHRGOT: ; $DF27 - jsr _disable_rom - jsr CHRGOT - jmp LDF21 - -.global _lda_5a_indy -_lda_5a_indy: ; $DF30 - jsr _disable_rom - lda ($5A),y - jmp _enable_rom - -.global _lda_5f_indy -_lda_5f_indy: ; $DF38 - jsr _disable_rom - lda ($5F),y - jmp _enable_rom - -.global _lda_ae_indx -_lda_ae_indx: ; $DF40 - jsr _disable_rom - lda ($AE,x) - jmp _enable_rom - -.global _lda_TXTPTR_indy -_lda_TXTPTR_indy: ; $DF48 - jsr _disable_rom - lda (TXTPTR),y - jmp _enable_rom - -.global _lda_TXTPTR_indx -_lda_TXTPTR_indx: ; DF50 - jsr _disable_rom - lda (TXTPTR,x) - jmp _enable_rom - -.global _lda_22_indy -_lda_22_indy: ; $DF58 - jsr _disable_rom - lda ($22),y - jmp _enable_rom - -.global _lda_8b_indy -_lda_8b_indy: ; $DF60 - jsr _disable_rom - lda ($8B),y - jmp _enable_rom - -_detokenize: ; $DF68 - jsr _disable_rom - jmp $A724 ; detokenize - -.global _list -_list: ; $DF6E - jsr _disable_rom - jmp $A6F3 ; part of LIST - -.global _print_banner_load_and_run -_print_banner_load_and_run: ; $DF74 - jsr _disable_rom - jsr $E422 ; print c64 banner - jsr _enable_rom - jmp load_and_run_program - -LDF80: cmp #$94 ; contents of $A000 in BASIC ROM - bne LDF8A ; BASIC ROM not visible - jsr _enable_rom - jmp kbd_handler - -LDF8A: jmp $EB48 ; default kdb vector - -.global _new_tokenize -_new_tokenize: ; $DF8D - jsr _enable_rom - jsr new_tokenize - jmp _disable_rom - -;padding - .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF - .byte $FF,$FF - -; calls into banks 0+1 -.global _new_ckout -_new_ckout: ; $DFC0 - jsr _enable_rom - jsr new_ckout - jmp _disable_rom - -.global _new_bsout -_new_bsout: ; $DFC9 - jsr _enable_rom - jmp new_bsout - -.global _new_clall -_new_clall: ; $DFCF - jsr _enable_rom - jmp new_clall - -.global _new_clrch -_new_clrch: ; $DFD5 - jsr _enable_rom - jmp new_clrch - -; padding - .byte $FF,$FF,$FF,$FF,$FF - -.global LDFE0 -LDFE0: ; XXX BUG ??? - .byte $FF,$FF,$FF ; ISC ($FFFF),X - .byte $FF,$FF,$FF ; ISC ($FFFF),X - .byte $FF,$FF ; ISC ($78FF),X - consumes "SEI" - - sei - lda #$42 ; bank 2 (Desktop, Freezer/Print) - sta $DFFF -.global _bar_irq -_bar_irq: - lda LDE00 ; $40 ??? - pha - lda $A000 ; ??? - pha - lda #$41 ; bank 1 (Notepad, BASIC (Menu Bar)) - sta $DFFF - -.global _a_colon_asterisk -_a_colon_asterisk: - .byte ':','*' -.global _a_colon_asterisk_end -_a_colon_asterisk_end: - -; ---------------------------------------------------------------- -; I/O Area ROM End -; ----------------------------------------------------------------