If detected, the program refuses to run, preventing a crash. The check only works with SpartaDOS. I don't have an overview which DOSes potentially use the RAM under the ROM. Or which other installed programs might use it. No additional runtime memory space is consumed, since the change is in the "system check" load chunk which gets replaced by the user program during loading.
244 lines
6.2 KiB
ArmAsm
244 lines
6.2 KiB
ArmAsm
;
|
|
; Atari startup system check
|
|
;
|
|
; This routine gets loaded prior to the main part of the executable
|
|
; and checks if the system is compatible to run the program.
|
|
; For the XL target it checks whether the system is an XL type one
|
|
; and that enough memory is installed (which isn't the case for a 600XL).
|
|
; For the non-XL target it checks whether there is enough memory
|
|
; installed to run the program.
|
|
; For both targets it checks that the program won't load below MEMLO.
|
|
; If one of the checks fails, the loading of the main program
|
|
; is aborted by jumping to DOSVEC.
|
|
;
|
|
; Christian Groessler, chris@groessler.org, 2013
|
|
;
|
|
|
|
;DEBUG = 1
|
|
|
|
.export __SYSTEM_CHECK__: absolute = 1
|
|
.import __SYSCHK_LOAD__
|
|
.import __STARTADDRESS__
|
|
|
|
; the following imports are only needed for the 'atari' target version
|
|
.import __BSS_SIZE__, __BSS_RUN__
|
|
.import __STACKSIZE__
|
|
.import __RESERVED_MEMORY__
|
|
|
|
.include "zeropage.inc"
|
|
.include "atari.inc"
|
|
|
|
|
|
.macro print_string text
|
|
.local start, cont
|
|
jmp cont
|
|
start: .byte text, ATEOL
|
|
cont: ldx #0 ; channel 0
|
|
lda #<start
|
|
sta ICBAL,x ; address
|
|
lda #>start
|
|
sta ICBAH,x
|
|
lda #<(cont - start)
|
|
sta ICBLL,x ; length
|
|
lda #>(cont - start)
|
|
sta ICBLH,x
|
|
lda #PUTCHR
|
|
sta ICCOM,x
|
|
jsr CIOV_org
|
|
.endmacro
|
|
|
|
.macro print_string2 addr, len
|
|
ldx #0 ; channel 0
|
|
lda #<addr
|
|
sta ICBAL,x ; address
|
|
lda #>addr
|
|
sta ICBAH,x
|
|
lda #<len
|
|
sta ICBLL,x ; length
|
|
lda #>len
|
|
sta ICBLH,x
|
|
lda #PUTCHR
|
|
sta ICCOM,x
|
|
jsr CIOV_org
|
|
.endmacro
|
|
|
|
|
|
; ------------------------------------------------------------------------
|
|
; code
|
|
|
|
.segment "SYSCHK"
|
|
|
|
rts ; for older DOSes which unconditionally run the first load chunk
|
|
|
|
.ifdef __ATARIXL__
|
|
|
|
; check for SpartaDOS and its usage of RAM below ROM
|
|
; return CF 0/1 for bad/ok
|
|
sdcheck:lda DOS
|
|
cmp #'S'
|
|
bne sdcrts0 ; not SpartaDOS, assume RAM is not used
|
|
lda DOS+1 ; SD version
|
|
cmp #$40 ; SD-X has $40 or higher
|
|
bcc sdcrts1 ; older versions (except maybe 1.x) always use the RAM under the ROM
|
|
ldy #31 ; offset for OSRMFLG
|
|
lda (DOSVEC),y ; get OSRMFLG
|
|
bne sdcrts1
|
|
|
|
sdcrts0:clc
|
|
rts
|
|
sdcrts1:sec
|
|
rts
|
|
|
|
ramrom_txt:
|
|
.byte "Memory under ROM is in use.", ATEOL
|
|
.byte "Cannot run this program.", ATEOL
|
|
ramrom_txt_len = * - ramrom_txt
|
|
|
|
lmemerrxl_txt:
|
|
.byte "Not enough memory to move screen", ATEOL
|
|
.byte "memory to low memory. Consider using", ATEOL
|
|
.byte "a higher load address.", ATEOL
|
|
lmemerrxl_txt_len = * - lmemerrxl_txt
|
|
|
|
; no XL machine
|
|
no_xl: print_string "This program needs an XL machine."
|
|
jmp fail
|
|
|
|
|
|
; ***** entry point (atarixl) *****
|
|
|
|
syschk: lda $fcd8 ; from ostype.s
|
|
cmp #$a2
|
|
beq no_xl
|
|
|
|
; we have an XL machine, now check memory
|
|
lda RAMSIZ
|
|
cmp #$80
|
|
bcs sys_ok
|
|
|
|
jmp mem_err
|
|
|
|
sys_ok: jsr sdcheck ; check for SpartaDOS-X, and if found, whether it uses the RAM under the ROM
|
|
bcc sd_ok
|
|
|
|
print_string2 ramrom_txt, ramrom_txt_len
|
|
jmp fail
|
|
|
|
sd_ok: .include "xlmemchk.inc" ; calculate lowest address we will use when we move the screen buffer down
|
|
|
|
lda MEMLO
|
|
cmp lowadr
|
|
lda MEMLO+1
|
|
sbc lowadr+1
|
|
bcc memlo_ok
|
|
|
|
; load address was too low
|
|
print_string2 lmemerrxl_txt, lmemerrxl_txt_len
|
|
jsr delay ; long text takes longer to read, give user additional time
|
|
jmp fail
|
|
|
|
.else ; above 'atarixl', below 'atari'
|
|
|
|
.define CIOV_org CIOV ; the print_string macros use CIOV_org, map this to CIOV
|
|
|
|
lmemerr_txt:
|
|
.byte "Program would load below MEMLO.", ATEOL
|
|
.byte "Consider using a higher load address.", ATEOL
|
|
lmemerr_txt_len = * - lmemerr_txt
|
|
|
|
|
|
; ***** entry point (atari) *****
|
|
|
|
syschk:
|
|
sec
|
|
lda MEMTOP
|
|
sbc #<__RESERVED_MEMORY__
|
|
sta tmp
|
|
lda MEMTOP+1
|
|
sbc #>__RESERVED_MEMORY__
|
|
sta tmp+1
|
|
lda tmp
|
|
sec
|
|
sbc #<__STACKSIZE__
|
|
sta tmp
|
|
lda tmp+1
|
|
sbc #>__STACKSIZE__
|
|
sta tmp+1
|
|
|
|
;tmp contains address which must be above .bss's end
|
|
|
|
lda tmp
|
|
cmp #<(__BSS_RUN__ + __BSS_SIZE__)
|
|
lda tmp+1
|
|
sbc #>(__BSS_RUN__ + __BSS_SIZE__)
|
|
|
|
bcc mem_err ; program doesn't fit into memory
|
|
|
|
lda MEMLO
|
|
cmp #<__STARTADDRESS__
|
|
lda MEMLO+1
|
|
sbc #>__STARTADDRESS__
|
|
bcc memlo_ok
|
|
|
|
; load address was too low
|
|
print_string2 lmemerr_txt, lmemerr_txt_len
|
|
jsr delay ; long text takes longer to read, give user additional time
|
|
jmp fail
|
|
|
|
.endif
|
|
|
|
; all is well(tm), launch the application
|
|
memlo_ok:
|
|
.ifdef DEBUG
|
|
print_string "Stage #1 OK"
|
|
jsr delay
|
|
.endif
|
|
rts
|
|
|
|
; not enough memory
|
|
mem_err:print_string "Not enough memory."
|
|
fail: jsr delay
|
|
jmp (DOSVEC)
|
|
|
|
; short delay
|
|
.proc delay
|
|
|
|
lda #10
|
|
@loop: jsr delay1
|
|
clc
|
|
sbc #0
|
|
bne @loop
|
|
rts
|
|
|
|
delay1: ldx #0
|
|
ldy #0
|
|
@loop: dey
|
|
bne @loop
|
|
dex
|
|
bne @loop
|
|
rts
|
|
|
|
.endproc
|
|
|
|
end:
|
|
|
|
.ifndef __ATARIXL__
|
|
tmp: ; outside of the load chunk, some kind of poor man's .bss
|
|
.endif
|
|
|
|
; ------------------------------------------------------------------------
|
|
; Chunk header
|
|
|
|
.segment "SYSCHKHDR"
|
|
|
|
.word __SYSCHK_LOAD__
|
|
.word end - 1
|
|
|
|
; ------------------------------------------------------------------------
|
|
; Chunk "trailer" - sets INITAD
|
|
|
|
.segment "SYSCHKTRL"
|
|
|
|
.word INITAD
|
|
.word INITAD+1
|
|
.word syschk
|