1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-24 11:31:31 +00:00

Merge pull request #45 from groessler/something_to_pull

Atari XL target
This commit is contained in:
Oliver Schmidt 2013-10-01 12:02:02 -07:00
commit 2c19ec4753
21 changed files with 2397 additions and 96 deletions

View File

@ -1002,9 +1002,21 @@ CASETV = $E440 ;cassette handler vector table
DISKIV = $E450 ;vector to initialize DIO
DSKINV = $E453 ;vector to DIO
.ifdef __ATARIXL__
.ifndef SHRAM_HANDLERS
.import CIO_handler, SIO_handler, SETVBV_handler
.endif
.define CIOV CIO_handler
.define SIOV SIO_handler
.define SETVBV SETVBV_handler
CIOV_org = $E456 ;vector to CIO
SIOV_org = $E459 ;vector to SIO
SETVBV_org = $E45C ;vector to set VBLANK parameters
.else
CIOV = $E456 ;vector to CIO
SIOV = $E459 ;vector to SIO
SETVBV = $E45C ;vector to set VBLANK parameters
.endif
SYSVBV = $E45F ;vector to process immediate VBLANK
XITVBV = $E462 ;vector to process deferred VBLANK
SIOINV = $E465 ;vector to initialize SIO

View File

@ -0,0 +1,91 @@
# This config file provides a single big upper memory block (HIDDEN_RAM).
# To achieve this, it relocates the character generator from $E000 to CHARGEN.
# The runtime library must be compiled with CHARGEN_RELOC for this config
# file to work. See libsrc/atari/Makefile.inc.
FEATURES {
STARTADDRESS: default = $2400;
}
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTADDRESS__: type = export, value = %S;
syschk: type = import; # force inclusion of SYSCHK
sramprep: type = import; # force inclusion of SRPREP
}
MEMORY {
ZP: file = "", define = yes, start = $0082, size = $007E;
# just $FFFF
HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
SYSCHKHDR: file = %O, start = $0000, size = $0004;
SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "shadow RAM preparation" load chunk
SRPREPHDR: file = %O, start = $0000, size = $0004;
SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
SRPREPTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
MAINHDR: file = %O, start = $0000, size = $0004;
RAM: file = %O, define = yes, start = %S +
__LOWDATA_SIZE__, size = $D000 -
__STACKSIZE__ -
%S -
__LOWDATA_SIZE__;
# defines entry point into program
TRAILER: file = %O, start = $0000, size = $0006;
# address of relocated character generator
CHARGEN: file = "", define = yes, start = $D800, size = $0400;
# memory beneath the ROM
HIDDEN_RAM: file = "", define = yes, start = $DC00, size = $FFF0 - $DC00;
}
SEGMENTS {
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes;
SRPREPHDR: load = SRPREPHDR, type = ro;
LOWDATA: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREP and RAM
SRPREP: load = SRPREPCHNK, type = rw, define = yes;
SHADOW_RAM: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes;
SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes;
SRPREPTRL: load = SRPREPTRL, type = ro;
MAINHDR: load = MAINHDR, type = ro;
STARTUP: load = RAM, type = ro, define = yes;
LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
INIT: load = RAM, type = ro, optional = yes;
CODE: load = RAM, type = ro, define = yes;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
AUTOSTRT: load = TRAILER, type = ro;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = INIT;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

View File

@ -1,48 +1,100 @@
FEATURES {
STARTADDRESS: default = $2E00;
STARTADDRESS: default = $2400;
}
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay
__RESERVED_MEMORY__: type = weak, value = $0000;
__STARTADDRESS__: type = export, value = %S;
syschk: type = import; # force inclusion of SYSCHK
sramprep: type = import; # force inclusion of SRPREP
}
MEMORY {
ZP: file = "", define = yes, start = $0082, size = $007E;
HEADER: file = %O, start = $0000, size = $0006;
RAM: file = %O, start = %S + __OVERLAYSIZE__, size = $BC20 - __STACKSIZE__ - __OVERLAYSIZE__ - %S;
TRAILER: file = %O, start = $0000, size = $0006;
OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__;
OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__;
OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__;
OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__;
OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__;
OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__;
OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__;
OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__;
ZP: file = "", define = yes, start = $0082, size = $007E;
# just $FFFF
HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
SYSCHKHDR: file = %O, start = $0000, size = $0004;
SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "shadow RAM preparation" load chunk
SRPREPHDR: file = %O, start = $0000, size = $0004;
SRPREPCHNK: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = $7C20 - %S - __OVERLAYSIZE__ - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
SRPREPTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
MAINHDR: file = %O, start = $0000, size = $0004;
RAM: file = %O, define = yes, start = %S +
__OVERLAYSIZE__ +
__LOWDATA_SIZE__, size = $D000 -
__STACKSIZE__ -
%S -
__OVERLAYSIZE__ -
__LOWDATA_SIZE__;
# defines entry point into program
TRAILER: file = %O, start = $0000, size = $0006;
# memory beneath the ROM preceeding the character generator
HIDDEN_RAM2: file = "", define = yes, start = $D800, size = $0800;
# address of relocated character generator (same addess as ROM version)
CHARGEN: file = "", define = yes, start = $E000, size = $0400;
# memory beneath the ROM
HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFF0 - $E400;
# overlays
OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__;
OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__;
OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__;
OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__;
OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__;
OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__;
OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__;
OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__;
}
SEGMENTS {
EXEHDR: load = HEADER, type = ro;
STARTUP: load = RAM, type = ro, define = yes;
LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
INIT: load = RAM, type = ro, optional = yes;
CODE: load = RAM, type = ro, define = yes;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
ZPSAVE: load = RAM, type = bss, define = yes;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
AUTOSTRT: load = TRAILER, type = ro;
OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes;
SRPREPHDR: load = SRPREPHDR, type = ro;
LOWDATA: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREP and RAM
SRPREP: load = SRPREPCHNK, type = rw, define = yes;
SHADOW_RAM: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes;
SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM2, type = rw, define = yes, optional = yes;
SRPREPTRL: load = SRPREPTRL, type = ro;
MAINHDR: load = MAINHDR, type = ro;
STARTUP: load = RAM, type = ro, define = yes;
LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
INIT: load = RAM, type = ro, optional = yes;
CODE: load = RAM, type = ro, define = yes;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
AUTOSTRT: load = TRAILER, type = ro;
OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
}
FEATURES {
CONDES: type = constructor,

View File

@ -1,28 +1,76 @@
FEATURES {
STARTADDRESS: default = $2E00;
STARTADDRESS: default = $2400;
}
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__RESERVED_MEMORY__: type = weak, value = $0000;
__STARTADDRESS__: type = export, value = %S;
syschk: type = import; # force inclusion of SYSCHK
sramprep: type = import; # force inclusion of SRPREP
}
MEMORY {
ZP: file = "", define = yes, start = $0082, size = $007E;
HEADER: file = %O, start = $0000, size = $0006;
RAM: file = %O, start = %S, size = $BC20 - __STACKSIZE__ - %S;
TRAILER: file = %O, start = $0000, size = $0006;
ZP: file = "", define = yes, start = $0082, size = $007E;
# just $FFFF
HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
SYSCHKHDR: file = %O, start = $0000, size = $0004;
SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "shadow RAM preparation" load chunk
SRPREPHDR: file = %O, start = $0000, size = $0004;
SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
SRPREPTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
MAINHDR: file = %O, start = $0000, size = $0004;
RAM: file = %O, define = yes, start = %S +
__LOWDATA_SIZE__, size = $D000 -
__STACKSIZE__ -
%S -
__LOWDATA_SIZE__;
# defines entry point into program
TRAILER: file = %O, start = $0000, size = $0006;
# memory beneath the ROM preceeding the character generator
HIDDEN_RAM2: file = "", define = yes, start = $D800, size = $0800;
# address of relocated character generator (same addess as ROM version)
CHARGEN: file = "", define = yes, start = $E000, size = $0400;
# memory beneath the ROM
HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFF0 - $E400;
}
SEGMENTS {
EXEHDR: load = HEADER, type = ro;
STARTUP: load = RAM, type = ro, define = yes;
LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
INIT: load = RAM, type = ro, optional = yes;
CODE: load = RAM, type = ro, define = yes;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
AUTOSTRT: load = TRAILER, type = ro;
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes;
SRPREPHDR: load = SRPREPHDR, type = ro;
LOWDATA: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREP and RAM
SRPREP: load = SRPREPCHNK, type = rw, define = yes;
SHADOW_RAM: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes;
SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM2, type = rw, define = yes, optional = yes;
SRPREPTRL: load = SRPREPTRL, type = ro;
MAINHDR: load = MAINHDR, type = ro;
STARTUP: load = RAM, type = ro, define = yes;
LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
INIT: load = RAM, type = ro, optional = yes;
CODE: load = RAM, type = ro, define = yes;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
AUTOSTRT: load = TRAILER, type = ro;
}
FEATURES {
CONDES: type = constructor,

View File

@ -14,3 +14,20 @@
# needs DEFAULT_DEVICE to be defined, otherwise no effect
CA65FLAGS += -D NUMDRVS=4 -D LINEBUF=80 -D UCASE_FILENAME=1 -D DEFAULT_DEVICE=1 -D DYNAMIC_DD=1
# The following defines are only used by the 'atarixl' target:
#
# CHARGEN_RELOC - If defined, CHBAS and CHBASE are updated when
# enabling or disabling the ROM.
# If the ROM is enabled, $E0 is written to CHBAS
# and CHBASE.
# If the ROM is disabled, the upper byte of
# __CHARGEN_START__ is written to CHBAS and CHBASE.
# USEWSYNC - If defined, the code waits for horizontal retrace
# before switching the ROM and updating CHBAS and
# CHBASE. This define only has effect if CHARGEN_RELOC
# is also defined.
# Disabled by default, you should enable it if the linker script relocates the
# character generator (like atarixl-largehimem.cfg).
#CA65FLAGS += -D CHARGEN_RELOC -D USEWSYNC

View File

@ -7,22 +7,28 @@
.include "atari.inc"
.export _cgetc,setcursor
.import KEYBDV_handler
.import cursor,mul40
_cgetc:
jsr setcursor
lda #12
sta ICAX1Z ; fix problems with direct call to KEYBDV
.ifndef __ATARIXL__
jsr @1
.else
jsr KEYBDV_handler
.endif
ldx #0
rts
.ifndef __ATARIXL__
@1: lda KEYBDV+5
pha
lda KEYBDV+4
pha
lda #12
sta ICAX1Z ; fix problems with direct call to KEYBDV
rts
.endif
.proc setcursor

View File

@ -15,6 +15,14 @@
.import callmain, zerobss
.import __STARTUP_LOAD__, __BSS_LOAD__
.import __RESERVED_MEMORY__
.import __RAM_START__, __RAM_SIZE__
.ifdef __ATARIXL__
.import __STACKSIZE__
.import sram_init
.import scrdev
.import findfreeiocb
.include "save_area.inc"
.endif
.include "zeropage.inc"
.include "atari.inc"
@ -25,6 +33,11 @@
.segment "EXEHDR"
.word $FFFF
.ifdef __ATARIXL__
.segment "MAINHDR"
.endif
.word __STARTUP_LOAD__
.word __BSS_LOAD__ - 1
@ -40,6 +53,12 @@
; Real entry point:
start:
.ifdef __ATARIXL__
jsr sram_init
.endif
; Clear the BSS data
jsr zerobss
@ -47,14 +66,16 @@
; Setup the stack
tsx
stx spsave
stx SP_save
.ifndef __ATARIXL__
; Report memory usage
lda APPMHI
sta appmsav ; remember old APPMHI value
sta APPMHI_save ; remember old APPMHI value
lda APPMHI+1
sta appmsav+1
sta APPMHI_save+1
sec
lda MEMTOP
@ -66,6 +87,15 @@
sta APPMHI+1
sta sp+1 ; setup runtime stack part 2
.else
lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
sta sp
lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
sta sp+1
.endif
; Call module constructors
jsr initlib
@ -73,14 +103,14 @@
; Set left margin to 0
lda LMARGN
sta old_lmargin
sta LMARGN_save
ldy #0
sty LMARGN
; Set keyb to upper/lowercase mode
ldx SHFLOK
stx old_shflok
stx SHFLOK_save
sty SHFLOK
; Initialize conio stuff
@ -98,26 +128,71 @@ _exit: jsr donelib ; Run module destructors
; Restore system stuff
ldx spsave
ldx SP_save
txs ; Restore stack pointer
; Restore left margin
lda old_lmargin
lda LMARGN_save
sta LMARGN
; Restore kb mode
lda old_shflok
lda SHFLOK_save
sta SHFLOK
; Restore APPMHI
lda appmsav
lda APPMHI_save
sta APPMHI
lda appmsav+1
lda APPMHI_save+1
sta APPMHI+1
.ifdef __ATARIXL__
; Atari XL target stuff...
lda PORTB_save
sta PORTB
lda RAMTOP_save
sta RAMTOP
lda MEMTOP_save
sta MEMTOP
lda MEMTOP_save+1
sta MEMTOP+1
; Issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) in
; order to restore screen memory to its defailt location just
; before the ROM.
jsr findfreeiocb
; Reopen it in Graphics 0
lda #OPEN
sta ICCOM,x
lda #OPNIN | OPNOT
sta ICAX1,x
lda #0
sta ICAX2,x
lda #<scrdev
sta ICBAL,x
lda #>scrdev
sta ICBAH,x
lda #3
sta ICBLL,x
lda #0
sta ICBLH,x
jsr CIOV_org
; No error checking here, shouldn't happen(tm), and no way to
; recover anyway.
lda #CLOSE
sta ICCOM,x
jsr CIOV_org
.endif
; Turn on cursor
ldx #0
@ -133,13 +208,15 @@ _exit: jsr donelib ; Run module destructors
.bss
spsave: .res 1
appmsav: .res 1
old_shflok: .res 1
old_lmargin: .res 1
SP_save: .res 1
SHFLOK_save: .res 1
LMARGN_save: .res 1
.ifndef __ATARIXL__
APPMHI_save: .res 2
.endif
.segment "AUTOSTRT"
.word RUNAD ; defined in atari.inc
.word RUNAD+1
.word __STARTUP_LOAD__ + 1
.word start

View File

@ -15,6 +15,7 @@
.import clriocb
.import fdtoiocb
.import newfd
.import scrdev
.importzp tmp1,tmp2,tmp3
.include "atari.inc"
@ -105,8 +106,3 @@ cioerr: sty tmp3 ; remember error code
jmp __mappederrno
.endproc ; __graphics
.rodata
scrdev: .byte "S:", 0

View File

@ -6,6 +6,10 @@
.import callirq
.include "atari.inc"
.ifdef __ATARIXL__
.import __CHARGEN_START__
.include "romswitch.inc"
.endif
; ------------------------------------------------------------------------
@ -39,7 +43,29 @@ doneirq:
IRQStub:
cld ; Just to be sure
.ifdef __ATARIXL__
pha
.ifdef CHARGEN_RELOC
lda CHBAS
pha
.endif
lda PORTB
pha
and #$FE
sta PORTB ; disable ROM
set_chbase >__CHARGEN_START__
.endif
jsr callirq ; Call the functions
.ifdef __ATARIXL__
pla
sta PORTB ; restore old ROM setting
.ifdef CHARGEN_RELOC
pla
sta CHBAS
sta CHBASE
.endif
pla
.endif
jmp IRQInd ; Jump to the saved IRQ vector
; ------------------------------------------------------------------------

View File

@ -7,4 +7,9 @@
em_libref := _exit
joy_libref := _exit
.ifdef __ATARIXL__
.import CIO_handler
tgi_libref := CIO_handler
.else
tgi_libref := _exit
.endif

View File

@ -40,8 +40,40 @@
.export _get_ostype
.proc _get_ostype
.include "atari.inc"
.include "romswitch.inc"
.ifdef __ATARIXL__
.import __CHARGEN_START__
.segment "LOWCODE"
.macro disable_rom_save_a
pha
disable_rom
pla
.endmacro
.else ; above atarixl, below atari
.macro disable_rom_save_a
.endmacro
.endif ; .ifdef __ATARIXL__
; unknown ROM
_unknown:
lda #0
tax
disable_rom_save_a
rts
_get_ostype:
enable_rom
lda $fcd8
cmp #$a2
beq _400800
@ -63,13 +95,7 @@
and #%00111000
ora #%11
_fin: ldx #0
rts
; unknown ROM
_unknown:
lda #0
tax
disable_rom_save_a
rts
; 1200XL ROM
@ -148,5 +174,3 @@ _400800_3:
lda #%00010001
bne _fin
.endproc

101
libsrc/atari/romswitch.inc Normal file
View File

@ -0,0 +1,101 @@
;
; Macros to disable and enable the ROM on Atari XL systems.
;
; Christian Groessler, chris@groessler.org, 19-Sep-2013
;
;
; Defines which modify the operation of the macros:
;
; CHARGEN_RELOC: If defined, CHBAS and CHBASE are updated when
; enabling or disabling the ROM.
; If the ROM is enabled, $E0 is written to CHBAS
; and CHBASE.
; If the ROM is disabled, the upper byte of
; __CHARGEN_START__ is written to CHBAS and CHBASE.
; USEWSYNC: If defined, the code waits for horizontal retrace
; before switching the ROM and updating CHBAS and
; CHBASE. This define only has effect if CHARGEN_RELOC
; is also defined.
.ifdef __ATARIXL__
.ifdef CHARGEN_RELOC
.macro set_chbase val
lda #val
sta CHBAS
sta CHBASE
.endmacro
.else
.macro set_chbase val
.endmacro
.endif ; .ifdef CHARGEN_RELOC
.if .defined(USEWSYNC) .and .defined(CHARGEN_RELOC)
.macro wsync
sta WSYNC
.endmacro
.else ; above
.macro wsync
.endmacro
.endif
; "disable ROM" macros
.macro disable_rom
lda PORTB
and #$fe
wsync
sta PORTB
set_chbase >__CHARGEN_START__
.endmacro
.macro disable_rom_quick
lda PORTB
and #$fe
sta PORTB
set_chbase >__CHARGEN_START__
.endmacro
.macro disable_rom_val val
lda val
wsync
sta PORTB
set_chbase >__CHARGEN_START__
.endmacro
; "enable ROM" macros
.macro enable_rom
lda PORTB
ora #1
wsync
sta PORTB
set_chbase $E0
.endmacro
.macro enable_rom_quick
lda PORTB
ora #1
sta PORTB
set_chbase $E0
.endmacro
.else ; above __ATARIXL__, below not
.macro disable_rom
.endmacro
.macro enable_rom
.endmacro
.endif

View File

@ -0,0 +1,13 @@
;
; Atari XL, shared data between 2nd load chunk and main chunk, header file
;
; Contains old values of modified system variables and ports.
;
; Christian Groessler, chris@groessler.org, 2013
;
.import SAVMSC_save
.import MEMTOP_save
.import APPMHI_save
.import RAMTOP_save
.import PORTB_save

25
libsrc/atari/save_area.s Normal file
View File

@ -0,0 +1,25 @@
;
; Atari XL, shared data between 2nd load chunk and main chunk, definition file
;
; Contains old values of modified system variables and ports.
;
; Christian Groessler, chris@groessler.org, 2013
;
.ifdef __ATARIXL__
.export SAVMSC_save
.export MEMTOP_save
.export APPMHI_save
.export RAMTOP_save
.export PORTB_save
.segment "LOWDATA"
SAVMSC_save: .res 2
MEMTOP_save: .res 2
APPMHI_save: .res 2
RAMTOP_save: .res 1
PORTB_save: .res 1
.endif

7
libsrc/atari/scrdev.s Normal file
View File

@ -0,0 +1,7 @@
; Name of the "screen" device
.export scrdev
.rodata
scrdev: .byte "S:", 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,405 @@
;
; Atari XL shadow RAM preparation routines
;
; Tasks:
; - move screen memory below load address
; - copy ROM chargen to its new place
; - copy shadow RAM contents to their destination
;
; Christian Groessler, chris@groessler.org, 2013
;
;DEBUG = 1
.ifdef __ATARIXL__
.export sramprep
.import __SRPREP_LOAD__, __SRPREPCHNK_LAST__
.import __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__, __SHADOW_RAM_RUN__
.import __SHADOW_RAM2_LOAD__, __SHADOW_RAM2_SIZE__, __SHADOW_RAM2_RUN__
.import __CHARGEN_START__, __CHARGEN_SIZE__
.import __STARTADDRESS__ ; needed by xlmemchk.inc
.include "zeropage.inc"
.include "atari.inc"
.include "save_area.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
; ------------------------------------------------------------------------
; EXE load chunk header
.segment "SRPREPHDR"
.word __SRPREP_LOAD__
.word __SRPREPCHNK_LAST__ - 1
; ------------------------------------------------------------------------
; Actual code
.segment "SRPREP"
sramprep:
.ifdef DEBUG
print_string "entering stage #2"
.endif
; save values of modified system variables and ports
lda RAMTOP
sta RAMTOP_save
lda MEMTOP
sta MEMTOP_save
lda MEMTOP+1
sta MEMTOP_save+1
lda APPMHI
sta APPMHI_save
lda APPMHI+1
sta APPMHI_save+1
lda PORTB
sta PORTB_save
; disable BASIC
lda PORTB
ora #2
sta PORTB
.include "xlmemchk.inc" ; calculate lowest address used and new value for RAMTOP
ldx lowadr
stx MEMTOP
lda lowadr+1
sta MEMTOP+1
lda lodadr+1
sta RAMTOP
; set APPMHI to MEMLO (+ 1 for sanity)
lda MEMLO
clc
adc #1
sta APPMHI
lda MEMLO+1
adc #0
sta APPMHI+1
; issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) to move screen memory down
jsr findfreeiocb
.ifdef DEBUG ; only check in debug version, this shouldn't really happen(tm)
beq iocbok
print_string "Internal error, no free IOCB!"
jsr delay
jsr delay
jsr delay
jsr restore ; restore stuff we've changed
jmp (DOSVEC) ; abort loading
iocbok:
.endif
; Reopen it in Graphics 0
lda #OPEN
sta ICCOM,x
lda #OPNIN | OPNOT
sta ICAX1,x
lda #0
sta ICAX2,x
lda #<screen_device
sta ICBAL,x
lda #>screen_device
sta ICBAH,x
lda #<screen_device_length
sta ICBLL,x
lda #>screen_device_length
sta ICBLH,x
jsr CIOV_org
bpl scrok
; shouldn't happen(tm)
print_string "Internal error, aborting..."
jsr delay
jsr delay
jsr delay
jsr restore ; restore stuff we've changed
jmp (DOSVEC) ; abort loading
scrok: ; now close it again -- we don't need it anymore
lda #CLOSE
sta ICCOM,x
jsr CIOV_org
; copy chargen to low memory, just after the next possible address beyond our loaded chunk data
.ifdef DEBUG
print_string "copy chargen to low memory"
.endif
lda #>__SRPREPCHNK_LAST__
sta ptr3+1
lda #<__SRPREPCHNK_LAST__
sta ptr3
beq cg_addr_ok
; page align the new chargen address
inc ptr3+1
lda #0
sta ptr3
cg_addr_ok:
lda ptr3+1
and #3
beq cg_addr_ok2
; align to next 1K boundary
lda ptr3+1
and #$fc
clc
adc #4
sta ptr3+1
cg_addr_ok2:
lda #<DCSORG
sta ptr1
lda #>DCSORG
sta ptr1+1
lda ptr3
sta ptr2
lda ptr3+1
pha ; needed later to set CHBAS/CHBASE
sta ptr2+1
lda #>__CHARGEN_SIZE__
sta tmp2
lda #<__CHARGEN_SIZE__
sta tmp1
jsr memcopy
.ifdef DEBUG
print_string "now setting up high memory"
.endif
; disable ROM
sei
ldx #0
stx NMIEN ; disable NMI
lda PORTB
and #$fe
tax
pla ; get temp. chargen address
sta WSYNC ; wait for horiz. retrace
stx PORTB ; now ROM is mapped out
; switch to temporary chargen
sta CHBASE
sta CHBAS
; copy shadow RAM contents to their destination (segment SHADOW_RAM)
lda #<__SHADOW_RAM_SIZE__
bne do_copy
lda #>__SHADOW_RAM_SIZE__
beq no_copy ; we have no shadow RAM contents
; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
do_copy:lda #<__SHADOW_RAM_LOAD__
sta ptr1
lda #>__SHADOW_RAM_LOAD__
sta ptr1+1
lda #<__SHADOW_RAM_RUN__
sta ptr2
lda #>__SHADOW_RAM_RUN__
sta ptr2+1
lda #<__SHADOW_RAM_SIZE__
sta tmp1
lda #>__SHADOW_RAM_SIZE__
sta tmp2
jsr memcopy
no_copy:
; copy shadow RAM #2 contents to their destination (segment SHADOW_RAM2)
lda #<__SHADOW_RAM2_SIZE__
bne do_copy2
lda #>__SHADOW_RAM2_SIZE__
beq no_copy2 ; we have no shadow RAM contents
; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len
do_copy2:
lda #<__SHADOW_RAM2_LOAD__
sta ptr1
lda #>__SHADOW_RAM2_LOAD__
sta ptr1+1
lda #<__SHADOW_RAM2_RUN__
sta ptr2
lda #>__SHADOW_RAM2_RUN__
sta ptr2+1
lda #<__SHADOW_RAM2_SIZE__
sta tmp1
lda #>__SHADOW_RAM2_SIZE__
sta tmp2
jsr memcopy
no_copy2:
; copy chargen to its new (final) location
lda ptr3
sta ptr1
lda ptr3+1
sta ptr1+1
lda #<__CHARGEN_START__
sta ptr2
lda #>__CHARGEN_START__
sta ptr2+1
lda #>__CHARGEN_SIZE__
sta tmp2
lda #<__CHARGEN_SIZE__
sta tmp1
jsr memcopy
; re-enable ROM
lda PORTB
ora #1
ldx #>DCSORG
sta WSYNC ; wait for horiz. retrace
sta PORTB
stx CHBASE
stx CHBAS
lda #$40
sta NMIEN ; enable VB again
cli ; and enable IRQs
.ifdef DEBUG
print_string "Stage #2 OK"
print_string "loading main chunk"
jsr delay
.endif
rts
.include "findfreeiocb.inc"
; routine taken from http://www.obelisk.demon.co.uk/6502/algorithms.html
;
; copy memory
; ptr1 - source
; ptr2 - destination
; tmp2:tmp1 - len
.proc memcopy
ldy #0
ldx tmp2
beq last
pagecp: lda (ptr1),y
sta (ptr2),y
iny
bne pagecp
inc ptr1+1
inc ptr2+1
dex
bne pagecp
last: cpy tmp1
beq done
lda (ptr1),y
sta (ptr2),y
iny
bne last
done: rts
.endproc
; clean up after a fatal error
restore:lda RAMTOP_save
sta RAMTOP
lda MEMTOP_save
sta MEMTOP
lda MEMTOP_save+1
sta MEMTOP+1
lda APPMHI_save
sta APPMHI
lda APPMHI_save+1
sta APPMHI+1
rts
; 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
.ifdef DEBUG
.byte "HERE ****************** HERE ***************>>>>>>"
sramsize:
.word __SHADOW_RAM_SIZE__
.endif ; .ifdef DEBUG
screen_device: .byte "S:",0
screen_device_length = * - screen_device
.ifdef DEBUG
.byte " ** srprep ** end-->"
.endif
; ------------------------------------------------------------------------
; Provide empty SHADOW_RAM and SHADOW_RAM2 segments in order that the
; linker is happy if the user program doesn't have these segments.
.segment "SHADOW_RAM"
.segment "SHADOW_RAM2"
; ------------------------------------------------------------------------
; EXE load chunk "trailer" - sets INITAD
.segment "SRPREPTRL"
.word INITAD
.word INITAD+1
.word sramprep
.endif ; .ifdef __ATARIXL__

View File

@ -8,7 +8,6 @@
;
.include "atari.inc"
.include "errno.inc"
.export __sysrmdir
.import __sysremove
.import __dos_type
@ -17,7 +16,6 @@
.ifdef UCASE_FILENAME
.import ucase_fn
.import addysp
.importzp sreg
.importzp tmp3
.ifdef DEFAULT_DEVICE
.importzp tmp2

157
libsrc/atari/system_check.s Normal file
View File

@ -0,0 +1,157 @@
;
; Atari XL 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.
; It checks whether the system is an XL type one and that enough
; memory is installed (which isn't the case for a 600XL).
; If the system doesn't qualify, the loading of the main program
; is aborted by jumping to DOSVEC.
;
; Christian Groessler, chris@groessler.org, 2013
;
;DEBUG = 1
.ifdef __ATARIXL__
.export syschk
.import __SYSCHK_LOAD__
.import __STARTADDRESS__ ; needed by xlmemchk.inc
.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
; ------------------------------------------------------------------------
; Chunk header
.segment "SYSCHKHDR"
.word __SYSCHK_LOAD__
.word end - 1
; ------------------------------------------------------------------------
; Actual code
.segment "SYSCHK"
; no XL machine
no_xl: print_string "This program needs an XL machine."
jmp fail
; entry point
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
; not enough memory
print_string "Not enough memory."
fail: jsr delay
jmp (DOSVEC)
sys_ok:
.include "xlmemchk.inc" ; calculate lowest address we will use when we move the screen buffer down
sec
lda MEMLO
sbc lowadr
lda MEMLO+1
sbc lowadr+1
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
; all is well(tm), launch the application
memlo_ok:
.ifdef DEBUG
print_string "Stage #1 OK"
jsr delay
.endif
rts
lmemerr_txt:
.byte "Not enough memory to move screen", ATEOL
.byte "memory to low memory. Consider using", ATEOL
.byte "a higher load address.", ATEOL
lmemerr_txt_len = * - lmemerr_txt
; short delay
.proc delay
lda #10
l: jsr delay1
clc
sbc #0
bne l
rts
delay1: ldx #0
ldy #0
loop: dey
bne loop
dex
bne loop
rts
.endproc
end:
; ------------------------------------------------------------------------
; Chunk "trailer" - sets INITAD
.segment "SYSCHKTRL"
.word INITAD
.word INITAD+1
.word syschk
.endif ; .ifdef __ATARIXL__

View File

@ -4,6 +4,12 @@
.macpack longbranch
.ifdef __ATARIXL__
CIO_vec := my_CIOV
.else
CIO_vec := CIOV
.endif
; ******************************************************************************
; ----------------------------------------------------------------------
@ -18,7 +24,7 @@
.byte $74, $67, $69 ; "tgi"
.byte TGI_API_VERSION ; TGI API version number
.addr $0000 ; Library reference
libref: .addr $0000 ; Library reference
.word x_res ; X resolution
.word y_res ; Y resolution
.byte colors ; Number of drawing colors
@ -111,6 +117,10 @@
text_dir:
.byte 0 ; Text direction,
.ifdef __ATARIXL__
my_CIOV:
.byte $4C, 0, 0
.endif
.code
; ******************************************************************************
@ -161,6 +171,17 @@ screen_device_length := * - screen_device
stx mask
.ifdef __ATARIXL__
; setup pointer to CIO
lda libref
sta my_CIOV+1
lda libref+1
sta my_CIOV+2
.endif
; Find a free IOCB
lda #$70
search: tax
@ -202,7 +223,7 @@ switch: lda #OPEN
sta ICBLL,x
lda #>screen_device_length
sta ICBLH,x
jsr CIOV
jsr CIO_vec
.if ::pages = 2
; Reserve 8K of high memory
@ -212,7 +233,7 @@ switch: lda #OPEN
; Close and reopen graphics
lda #CLOSE
sta ICCOM,x
jsr CIOV
jsr CIO_vec
; Reopen graphics
lda #OPEN
sta ICCOM,x
@ -228,7 +249,7 @@ switch: lda #OPEN
sta ICBLL,x
lda #>screen_device_length
sta ICBLH,x
jsr CIOV
jsr CIO_vec
; Save screen pointers
lda SAVMSC + 1
sta p0scr
@ -271,7 +292,7 @@ exit: sta error
; Close the S: device
lda #CLOSE
sta ICCOM,x
jsr CIOV
jsr CIO_vec
; Reopen it in Graphics 0
lda #OPEN
@ -288,12 +309,12 @@ exit: sta error
sta ICBLL,x
lda #>screen_device_length
sta ICBLH,x
jsr CIOV
jsr CIO_vec
; Now close it again; we don't need it anymore :)
lda #CLOSE
sta ICCOM,x
jmp CIOV
jmp CIO_vec
.endproc
; ******************************************************************************
@ -640,7 +661,7 @@ done10:
.endif
sta ATACHR
jmp CIOV
jmp CIO_vec
.else ; USE_CIO_LINE

119
libsrc/atari/xlmemchk.inc Normal file
View File

@ -0,0 +1,119 @@
;
; Christian Groessler, Jun-2013
;
; This routine is used in preparation to move the screen memory
; in front of the program.
;
; It calculates the value to put into RAMTOP for a subsequent
; "GRAPHICS 0" call, and the lowest address which will be used
; by the screen memory afterwards.
;
; inputs:
; __STARTADDRESS__ - load address of the program
; outputs:
; lodadr - (high byte only) value to
; write into RAMTOP
; lowadr - lowest address occupied by
; screen data
;
; When setting a display mode, the ROM takes the RAMTOP value
; and subtracts the size of the screen memory from it. This will
; become the new screen memory address.
; From this address it subtracts the size of the display list.
; This will become the new display list address.
; Screen memory cannot cross 4K boundaries and a display list
; cannot cross a 1K boundary.
;
; Work out a sane value for RAMTOP to prevent boundary crossing.
; RAMTOP is only one byte, it counts in memory pages.
;
; The ROM doesn't do this boundary checking, since it doesn't
; expect RAMTOP to have (rather) arbitrary values. For a
; "GRAPHICS 0" call and RAMTOP representing the possible physically
; available memory, boundary crossing cannot happen.
SCRBUFSZ = (40 * 24) ; size of mode 0 screen buffer
DLSZ = 32 ; size of mode 0 display list
scrmemtst:
; subtract screen memory size from our load address
lda lodadr
sec
sbc #<SCRBUFSZ
sta tstadr
lda lodadr+1
sbc #>SCRBUFSZ
sta tstadr+1
; check if a 4K boundary is crossed
lda lodadr+1
and #$f0
sta tmp
lda tstadr+1
and #$f0
cmp tmp
beq scrmemok
; if lodadr is at an exact 4K boundary, it's still ok
lda lodadr+1
and #$0f
beq scrmemok
; 4K boundary will be crossed, use this 4K boundary address as lodadr
al4k: lda lodadr+1
and #$f0
sta lodadr+1
bne scrmemtst
; not reached
.ifdef DEBUG
.byte "XLMEMCHK:>"
.endif
lodadr: .word __STARTADDRESS__ & $FF00 ; our program's load address, rounded down to page boundary
tstadr: .res 2
lowadr: .res 2
tmp: .res 1
; subtract display list size from calculated screen address
scrmemok:
lda tstadr
sec
sbc #<DLSZ
sta lowadr
lda tstadr+1
sbc #>DLSZ
sta lowadr+1
.if 0 ; this cannot happen
; check if a 1K boundary is crossed
lda tstadr+1
and #$fc
sta tmp
lda lowadr+1
and #$fc
cmp tmp
bne al4k ; 1K boundary will be crossed, decrease lodadr
.endif
; address of display list is ok
; decrease lowadr by two
lda lowadr
sec
sbc #2
sta lowadr
bcs dec_cont
dec lowadr+1
dec_cont: