From 60f03a34afa4518e28a1ba3453fb95740acd0148 Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Wed, 14 May 2014 07:03:46 -0700 Subject: [PATCH] Improvements to c64_0.oph startup/teardown code 16 additional bytes from the zero page are now available; the ZP locations from $02-$8F are now free for your program's use. Approximately 128 additional bytes in main RAM are now available, giving you free reign from $0800-$CFFF. Zero Page backup is now handled underneath the KERNAL's ROM, with the program epilogue safely handling swapping out the KERNAL for the duration of the switch. (IRQs are disabled, and NMI handling code is replicated and modified to not hurt anything.) Program exit is now handled by keyboard buffer and jumping through BASIC's warm reset vector. This technique lets programs play more nicely with PUCRUNCH and onefilers (which otherwise often confused BASIC as the BASIC prologue would change as part of decompression or link-loading). --- platform/README.txt | 8 ++++--- platform/c64_0.oph | 54 +++++++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/platform/README.txt b/platform/README.txt index ca183d6..7e1cfb2 100644 --- a/platform/README.txt +++ b/platform/README.txt @@ -6,11 +6,13 @@ c64_0.oph: A Commodore 64 equivalent to a modern compiler's "crt0.s" - it contains a .PRG file header, a short BASIC program that launches the machine language program, and a prologue and epilogue that prepare memory for your use and then clean it up again when you - are done. Memory locations $02 through $7F on the zero page are + are done. Memory locations $02 through $8F on the zero page are available for your use, and the program lives at the beginning - a contiguous block of RAM from $0800 through $CF81. The BASIC + a contiguous block of RAM from $0800 through $CFFF. The BASIC ROM is swapped out of memory (leaving $A000-$BFFF as RAM) for - the duration of your program. + the duration of your program. BASIC's working storage on the + zero page is backed up in the RAM underneath the KERNAL ROM + while your program runs. c64kernal.oph: A collection of standard aliases for the KERNAL routines on the Commodore 64. Names for these routines have been chosen to match diff --git a/platform/c64_0.oph b/platform/c64_0.oph index 7b64a59..f3b5e3a 100644 --- a/platform/c64_0.oph +++ b/platform/c64_0.oph @@ -5,8 +5,8 @@ ;; Include this at the TOP of your C64 program, and it will handle ;; hiding away the BASIC ROM and data and restoring it at the end. ;; -;; You will have a contiguous block of RAM from $0800 to $CF81, and -;; Zero Page access from $02 to $7F in the segment "zp". +;; You will have a contiguous block of RAM from $0800 to $CFFF, and +;; Zero Page access from $02 to $8F in the segment "zp". .word $0801 .org $0801 @@ -24,11 +24,16 @@ _next: .word 0 ; End of program .text .scope - ; Cache BASIC zero page at top of available RAM - ldx #$7E -* lda $01, x - sta $CF81, x - dex + ; Cache BASIC zero page underneath the KERNAL, while also + ; making RAM copies of the NMI routines + ldx #$00 +* lda $00, x + sta $e000, x + lda $fe00, x + sta $fe00, x + lda $ff00, x + sta $ff00, x + inx bne - ; Swap out the BASIC ROM for RAM @@ -40,20 +45,41 @@ _next: .word 0 ; End of program ; Run the real program jsr _main - ; Restore BASIC ROM - lda $01 - ora #$07 + ; Swap out KERNAL to expose cached BASIC ZP values + ; Block IRQs during this period. NMIs cannot be blocked, + ; but we copied enough of the processing code into the + ; RAM under the KERNAL that we can disable NMI processing + ; during this period + sei ; Disable IRQs + lda #$c1 ; Defang NMIs + sta $318 + + lda $01 ; Swap out KERNAL + and #$fd sta $01 ; Restore BASIC zero page - ldx #$7E -* lda $CF81, x + ldx #$8E +* lda $e001, x sta $01, x dex bne - - ; Back to BASIC - rts + ; Restore BASIC ROM, KERNAL, and interrupts + lda $01 + ora #$07 + sta $01 + lda #$47 ; Restore NMI vector + sta $318 + cli ; Re-enable interrupts + + ; Back to BASIC. We do this by clearing the keyboard + ; buffer and then jumping through the warm start + ; vector. This will more cleanly handle case where + ; the program has somehow modified BASIC's state, + ; such as running through PUCRUNCH or a onefiler. + stx $c6 ; .X is zero from previous loop + jmp ($a002) _main: ; Program follows...