From 1cc4fa9356a8a7ca17b3bd519dc818531a8e6b66 Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Sun, 2 Sep 2018 23:07:03 +0200 Subject: [PATCH] Atari: fix interrupt handling if extended memory is banked in Extendend memory is mapped over the main memory in the 0x4000..0x7FFF area. Many DOSes disable interrupts while extended memory is banked in, but not all (e.g. SpartaDOS-X). This change modifies the initial interrupt handler to map in main memory before chaining to the "worker" handlers. Since the initial interrupt handler uses a data segment to store the trampoline to chain to the original handler, introduce a new "LOWBSS" segment to hold this trampoline. Otherwise the trampoline may end up inside the 0x4000..0x7FFF area. Add a link time warning if "LOWCODE" segment lays within the extended memory window. --- cfg/atari-cart.cfg | 32 +++++++++++++++++--------------- cfg/atari-cassette.cfg | 1 + cfg/atari-overlay.cfg | 1 + cfg/atari.cfg | 1 + cfg/atarixl-largehimem.cfg | 1 + cfg/atarixl-overlay.cfg | 1 + cfg/atarixl.cfg | 1 + libsrc/atari/crt0.s | 9 +++++++++ libsrc/atari/irq.s | 21 +++++++++++++++------ 9 files changed, 47 insertions(+), 21 deletions(-) diff --git a/cfg/atari-cart.cfg b/cfg/atari-cart.cfg index 31d2cb1b9..16208f90d 100644 --- a/cfg/atari-cart.cfg +++ b/cfg/atari-cart.cfg @@ -10,23 +10,25 @@ SYMBOLS { __CARTFLAGS__: type = weak, value = $01; # see documentation for other possible values } MEMORY { - ZP: file = "", define = yes, start = $0082, size = $007E; - MAIN: file = "", define = yes, start = %S, size = __CARTSIZE__; - ROM: file = %O, define = yes, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - 6, fill = yes, fillval = $FF; - CARTID: file = %O, start = $BFFA, size = $0006; + ZP: file = "", define = yes, start = $0082, size = $007E; + MAIN: file = "", define = yes, start = %S, size = __CARTSIZE__; + ROM: file = %O, define = yes, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - 6, fill = yes, fillval = $FF; + CARTID: file = %O, start = $BFFA, size = $0006; + DISCARD: file = "", start = $0100, size = $FF00; } SEGMENTS { - ZEROPAGE: load = ZP, type = zp, optional = yes; - EXTZP: load = ZP, type = zp, optional = yes; - STARTUP: load = ROM, type = ro, define = yes, optional = yes; - LOWCODE: load = ROM, type = ro, define = yes, optional = yes; - ONCE: load = ROM, type = ro, optional = yes; - CODE: load = ROM, type = ro, define = yes; - RODATA: load = ROM, type = ro, optional = yes; - DATA: load = ROM, run = MAIN, type = rw, define = yes, optional = yes; - INIT: load = MAIN, type = bss, optional = yes; - BSS: load = MAIN, type = bss, define = yes, optional = yes; - CARTHDR: load = CARTID, type = ro; + ZEROPAGE: load = ZP, type = zp, optional = yes; + EXTZP: load = ZP, type = zp, optional = yes; + STARTUP: load = ROM, type = ro, define = yes, optional = yes; + LOWBSS: load = DISCARD, run = MAIN, type = rw, optional = yes; # not zero-initialized + LOWCODE: load = ROM, type = ro, define = yes, optional = yes; + ONCE: load = ROM, type = ro, optional = yes; + CODE: load = ROM, type = ro, define = yes; + RODATA: load = ROM, type = ro, optional = yes; + DATA: load = ROM, run = MAIN, type = rw, define = yes, optional = yes; + INIT: load = MAIN, type = bss, optional = yes; + BSS: load = MAIN, type = bss, define = yes, optional = yes; + CARTHDR: load = CARTID, type = ro; } FEATURES { CONDES: type = constructor, diff --git a/cfg/atari-cassette.cfg b/cfg/atari-cassette.cfg index 5e99c303e..465add95e 100644 --- a/cfg/atari-cassette.cfg +++ b/cfg/atari-cassette.cfg @@ -16,6 +16,7 @@ SEGMENTS { EXTZP: load = ZP, type = zp, optional = yes; CASHDR: load = MAIN, type = ro; STARTUP: load = MAIN, type = ro, define = yes, optional = yes; + LOWBSS: load = MAIN, type = rw, optional = yes; # not zero-initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; diff --git a/cfg/atari-overlay.cfg b/cfg/atari-overlay.cfg index 87e62d764..fdf2e983c 100644 --- a/cfg/atari-overlay.cfg +++ b/cfg/atari-overlay.cfg @@ -46,6 +46,7 @@ SEGMENTS { SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; + LOWBSS: load = MAIN, type = rw, optional = yes; # not zero-initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; diff --git a/cfg/atari.cfg b/cfg/atari.cfg index 4680a89ed..9e0ea474f 100644 --- a/cfg/atari.cfg +++ b/cfg/atari.cfg @@ -34,6 +34,7 @@ SEGMENTS { SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; + LOWBSS: load = MAIN, type = rw, optional = yes; # not zero-initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; diff --git a/cfg/atarixl-largehimem.cfg b/cfg/atarixl-largehimem.cfg index 56d2af15b..842a485a1 100644 --- a/cfg/atarixl-largehimem.cfg +++ b/cfg/atarixl-largehimem.cfg @@ -61,6 +61,7 @@ SEGMENTS { MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; + LOWBSS: load = MAIN, type = rw, optional = yes; # not zero-initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; diff --git a/cfg/atarixl-overlay.cfg b/cfg/atarixl-overlay.cfg index 923436497..f3a40b6a7 100644 --- a/cfg/atarixl-overlay.cfg +++ b/cfg/atarixl-overlay.cfg @@ -72,6 +72,7 @@ SEGMENTS { MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; + LOWBSS: load = MAIN, type = rw, optional = yes; # not zero-initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; diff --git a/cfg/atarixl.cfg b/cfg/atarixl.cfg index 197daace6..c2d331fab 100644 --- a/cfg/atarixl.cfg +++ b/cfg/atarixl.cfg @@ -59,6 +59,7 @@ SEGMENTS { MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; + LOWBSS: load = MAIN, type = rw, optional = yes; # not zero-initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; diff --git a/libsrc/atari/crt0.s b/libsrc/atari/crt0.s index d14567491..97b7d7e95 100644 --- a/libsrc/atari/crt0.s +++ b/libsrc/atari/crt0.s @@ -15,6 +15,7 @@ .import callmain, zerobss .import __RESERVED_MEMORY__ .import __MAIN_START__, __MAIN_SIZE__ + .import __LOWCODE_RUN__, __LOWCODE_SIZE__ .ifdef __ATARIXL__ .import __STACKSIZE__ .import sram_init @@ -199,3 +200,11 @@ LMARGN_save: .res 1 .ifndef __ATARIXL__ APPMHI_save: .res 2 .endif + +; ------------------------------------------------------------------------ + +.segment "LOWCODE" ; have at least one (empty) segment of LOWCODE, so that the next line works even if the program doesn't make use of this segment +.assert (__LOWCODE_RUN__ + __LOWCODE_SIZE__ <= $4000 || __LOWCODE_RUN__ > $7FFF || __LOWCODE_SIZE__ = 0), warning, "'lowcode area' reaches into $4000..$7FFF bank memory window" +; check for LOWBSS_SIZE = 0 not needed since the only file which uses LOWBSS (irq.s) also uses LOWCODE +; check for LOWCODE_RUN > $7FFF is mostly for cartridges, where this segment is loaded high (into cart ROM) +; there is a small chance that if the user loads the program really high, LOWCODE is above $7FFF, but LOWBSS is below -- no warning emitted in this case diff --git a/libsrc/atari/irq.s b/libsrc/atari/irq.s index 1878ea0a2..86fef609b 100644 --- a/libsrc/atari/irq.s +++ b/libsrc/atari/irq.s @@ -16,6 +16,8 @@ .segment "ONCE" initirq: + lda #$4C ; JMP opcode + sta IRQInd lda VVBLKD ldx VVBLKD+1 sta IRQInd+1 @@ -45,17 +47,22 @@ IRQStub: .ifdef CHARGEN_RELOC lda CHBAS pha +.endif .endif lda PORTB pha - and #$FE - sta PORTB ; disable ROM +.ifdef __ATARIXL__ + and #$FE ; disable ROM +.endif + ora #$10 ; map main memory into $4000..$7FFF area + sta PORTB +.ifdef __ATARIXL__ set_chbase >__CHARGEN_START__ .endif jsr callirq ; Call the functions -.ifdef __ATARIXL__ pla - sta PORTB ; restore old ROM setting + sta PORTB ; restore old memory settings +.ifdef __ATARIXL__ .ifdef CHARGEN_RELOC pla sta CHBAS @@ -66,6 +73,8 @@ IRQStub: ; ------------------------------------------------------------------------ -.data +.segment "LOWBSS" + +IRQInd: .res 3 -IRQInd: jmp $0000 +.end -- 2.39.2