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.
This commit is contained in:
Christian Groessler 2018-09-02 23:07:03 +02:00 committed by Oliver Schmidt
parent d199ca1460
commit 1cc4fa9356
9 changed files with 47 additions and 21 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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: jmp $0000
IRQInd: .res 3
.end