diff --git a/asminc/atari.inc b/asminc/atari.inc index 1fff3ebae..c60f6642d 100644 --- a/asminc/atari.inc +++ b/asminc/atari.inc @@ -101,11 +101,28 @@ SIO_FORMAT = $21 ;format disk (default density) SIO_FORMATS = $22 ;1050: format medium density SIO_CONFIG = $44 ;configure drive SIO_CONFIGSF = $4B ;slow/fast configure drive?? +SIO_RDPERCOM = $4E ;read PERCOM block (XF551) +SIO_WRPERCOM = $4F ;write PERCOM block (XF551) SIO_WRITE = $50 ;write sector SIO_READ = $52 ;read sector SIO_STAT = $53 ;get status information SIO_VERIFY = $56 ;verify sector SIO_WRITEV = $57 ;write sector with verify +SIO_WRITETRK = $60 ;write track (Speedy) +SIO_READTRK = $62 ;read track (Speedy) + +; SIO Status Code (DSTATS) +; Input: data direction +; Bit #7 - W (write operation) +; #6 - R (read operation) +; Output: status code +; $01 (001) -- OPERATION COMPLETE (NO ERRORS) +; $8A (138) -- DEVICE TIMEOUT (DOESN'T RESPOND) +; $8B (139) -- DEVICE NAK +; $8C (140) -- SERIAL BUS INPUT FRAMING ERROR +; $8E (142) -- SERIAL BUS DATA FRAME OVERRUN ERROR +; $8F (143) -- SERIAL BUS DATA FRAME CHECKSUM ERROR +; $90 (144) -- DEVICE DONE ERROR ; Character and Key Code Equates @@ -985,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 diff --git a/asminc/atmos.inc b/asminc/atmos.inc index 20bb806f1..6534a2ef0 100644 --- a/asminc/atmos.inc +++ b/asminc/atmos.inc @@ -18,21 +18,26 @@ FNAME_LEN = 16 ; maximum length of file-name ; --------------------------------------------------------------------------- ; Zero page +SCRPTR := $12 BASIC_BUF := $35 +CHARGOT := $E8 +TXTPTR := $E9 ; --------------------------------------------------------------------------- ; Low memory MODEKEY := $0209 -CAPSLOCK := $020C +CAPSLOCK := $020C ; $7F = not locked, $FF = locked PATTERN := $0213 -IRQVec := $0245 +IRQVec := $0245 ; "fast" interrupt vector JOINFLAG := $025A ; 0 = don't joiu, $4A = join BASIC programs VERIFYFLAG := $025B ; 0 = load, 1 = verify CURS_Y := $0268 CURS_X := $0269 STATUS := $026A +BACKGRND := $026B +FOREGRND := $026C TIMER3 := $0276 CFILE_NAME := $027F CFOUND_NAME := $0293 @@ -40,10 +45,13 @@ FILESTART := $02A9 FILEEND := $02AB AUTORUN := $02AD ; $00 = only load, $C7 = autorun LANGFLAG := $02AE ; $00 = BASIC, $80 = machine code +LOADERR := $02B1 KEYBUF := $02DF +PARMERR := $02E0 PARAM1 := $02E1 ; & $02E2 PARAM2 := $02E3 ; & $02E4 PARAM3 := $02E5 ; & $02E6 +BANGVEC := $02F5 ; --------------------------------------------------------------------------- @@ -92,3 +100,11 @@ POINT := $F1C8 PAPER := $F204 INK := $F210 PRINT := $F77C + +; Sound Effects +PING := $FA9F +SHOOT := $FAB5 +EXPLODE := $FACB +ZAP := $FAE1 +TICK := $FB14 +TOCK := $FB2A diff --git a/asminc/c128.inc b/asminc/c128.inc index 1fb8b397c..aac8678bf 100644 --- a/asminc/c128.inc +++ b/asminc/c128.inc @@ -6,6 +6,7 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +TXTPTR := $3D ; Pointer into BASIC source code TIME := $A0 ; 60HZ clock FNAM_LEN := $B7 ; Length of filename SECADR := $B9 ; Secondary address diff --git a/asminc/c64.inc b/asminc/c64.inc index f5dbcf549..f450fcc0b 100644 --- a/asminc/c64.inc +++ b/asminc/c64.inc @@ -6,6 +6,7 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +TXTPTR := $7A ; Pointer into BASIC source code TIME := $A0 ; 60 HZ clock FNAM_LEN := $B7 ; Length of filename SECADR := $B9 ; Secondary address diff --git a/asminc/cbm510.inc b/asminc/cbm510.inc index 827c507fc..abc363728 100644 --- a/asminc/cbm510.inc +++ b/asminc/cbm510.inc @@ -3,14 +3,17 @@ ; ; Taken from a kernal disassembly done by myself in 2000/2001. ; -; Ullrich von Bassewitz, 13.09.2001 +; 2001-09-13, Ullrich von Bassewitz +; 2013-08-26, Greg King ;----------------------------------------------------------------------------- ; Zeropage stuff -ExecReg = $00 -IndReg = $01 +ExecReg := $00 ; Controls execution memory bank +IndReg := $01 ; Controls indirect indexed load-store bank + +TXTPTR := $85 ; Far pointer into BASIC source code ; --------------------------------------------------------------------------- ; Screen size @@ -20,8 +23,11 @@ YSIZE = 25 ;----------------------------------------------------------------------------- ; I/O Definitions +; Note: These numbers aren't addresses. They are offsets from the start of +; each chip's register set. They are used in the indirect indexed addressing +; mode. -; I/O $d800: VIC +; I/O $d800: VIC-II VIC_SPR0_X = $00 VIC_SPR0_Y = $01 @@ -63,6 +69,9 @@ VIC_CTRL2 = $16 VIC_HLINE = $12 +VIC_LPEN_X = $13 +VIC_LPEN_Y = $14 + VIC_VIDEO_ADR = $18 VIC_IRR = $19 ; Interrupt request register @@ -75,7 +84,6 @@ VIC_BG_COLOR2 = $23 VIC_BG_COLOR3 = $24 - ; I/O $da00: SID 6581 SID_S1Lo = $00 @@ -112,7 +120,7 @@ SID_Noise = $1B SID_Read3 = $1C -; I/O $db00: CIA 6526 Inter Process Communication +; I/O $db00: CIA 6526, Inter Process Communication ; I/O $dc00: CIA 6526 .struct CIA @@ -176,7 +184,13 @@ SID_Read3 = $1C .endstruct -; Out video memory address +;----------------------------------------------------------------------------- +; Our video memory address -COLOR_RAM = $D400 ; System bank +COLOR_RAM := $D400 ; System bank + +;----------------------------------------------------------------------------- + +BASIC_BUF := $FB5E ; Bank 0 location of command-line +BASIC_BUF_LEN = 162 ; Maximum length of command-line diff --git a/asminc/cbm610.inc b/asminc/cbm610.inc index 94256eeb1..f442f5da8 100644 --- a/asminc/cbm610.inc +++ b/asminc/cbm610.inc @@ -1,16 +1,19 @@ ; -; Zeropage and I/O definitions for the CBM 610 +; Zero page variables and I/O definitions for the CBM 610 ; ; Taken from a kernal disassembly done by myself in 1987. ; -; Ullrich von Bassewitz, 28.09.1998 +; 1998-09-28, Ullrich von Bassewitz +; 2013-08-26, Greg King ; --------------------------------------------------------------------------- ; Zeropage stuff -ExecReg = $00 -IndReg = $01 +ExecReg := $00 ; Controls execution memory bank +IndReg := $01 ; Controls indirect indexed load-store bank + +TXTPTR := $85 ; Far pointer into BASIC source code ; --------------------------------------------------------------------------- ; Screen size @@ -29,7 +32,8 @@ YSIZE = 25 DATA .byte .endstruct -; I/O $db00: CIA 6526 Inter Process Communication + +; I/O $db00: CIA 6526, Inter Process Communication ; ; IPCcia = $db00 @@ -68,7 +72,6 @@ YSIZE = 25 ; cia = $dc00 - ; I/O $dd00: ACIA 6551 ; ; acia = $dd00 @@ -108,3 +111,7 @@ YSIZE = 25 ; tpi2 = $df00 +;----------------------------------------------------------------------------- + +BASIC_BUF := $FA5E ; Bank 1 location of command-line +BASIC_BUF_LEN = 162 ; Maximum length of command-line diff --git a/asminc/em-kernel.inc b/asminc/em-kernel.inc index 313bfc0bf..e7cdf9a70 100644 --- a/asminc/em-kernel.inc +++ b/asminc/em-kernel.inc @@ -55,7 +55,7 @@ ;------------------------------------------------------------------------------ ; The EMD API version, stored in EMD_HDR::VERSION -EMD_API_VERSION = $01 +EMD_API_VERSION = $02 ;------------------------------------------------------------------------------ ; The asm equivalent to the C em_copy structure diff --git a/asminc/joy-kernel.inc b/asminc/joy-kernel.inc index da22662b5..4fe5572cf 100644 --- a/asminc/joy-kernel.inc +++ b/asminc/joy-kernel.inc @@ -56,7 +56,7 @@ ;------------------------------------------------------------------------------ ; The JOY API version, stored in JOY_HDR::VERSION -JOY_API_VERSION = $02 +JOY_API_VERSION = $03 ;------------------------------------------------------------------------------ ; Variables diff --git a/asminc/mouse-kernel.inc b/asminc/mouse-kernel.inc index 9db47fcb8..d3ec9b30f 100644 --- a/asminc/mouse-kernel.inc +++ b/asminc/mouse-kernel.inc @@ -97,7 +97,7 @@ ;------------------------------------------------------------------------------ ; The mouse API version, stored in MOUSE_HDR::VERSION -MOUSE_API_VERSION = $03 +MOUSE_API_VERSION = $04 ;------------------------------------------------------------------------------ ; Bitmapped mouse driver flags, stored in MOUSE_HDR::FLAGS. diff --git a/asminc/pet.inc b/asminc/pet.inc index a3dadf48d..1ebf391f9 100644 --- a/asminc/pet.inc +++ b/asminc/pet.inc @@ -7,6 +7,7 @@ ; Zero page, Commodore stuff MEMSIZE := $34 ; Size of memory installed +TXTPTR := $77 ; Pointer into BASIC source code TIME := $8D ; 60HZ clock KEY_COUNT := $9E ; Number of keys in input buffer RVS := $9F ; Reverse flag @@ -24,6 +25,9 @@ SCR_LINELEN := $D5 ; Screen line length CURS_Y := $D8 ; Cursor row FNADR := $DA ; Pointer to file name +BASIC_BUF := $200 ; Location of command-line +BASIC_BUF_LEN = 81 ; Maximum length of command-line + KEY_BUF := $26F ; Keyboard buffer ;---------------------------------------------------------------------------- diff --git a/asminc/plus4.inc b/asminc/plus4.inc index 014c18e60..17e250508 100644 --- a/asminc/plus4.inc +++ b/asminc/plus4.inc @@ -7,6 +7,7 @@ ; Zero page, Commodore stuff TMPPTR := $22 ; Temporary ptr used by BASIC +TXTPTR := $3B ; Pointer into BASIC source code TIME := $A3 ; 60HZ clock FNAM_LEN := $AB ; Length of filename LFN := $AC ; Logical file number diff --git a/asminc/ser-kernel.inc b/asminc/ser-kernel.inc index fff9b1440..e59501da6 100644 --- a/asminc/ser-kernel.inc +++ b/asminc/ser-kernel.inc @@ -57,7 +57,7 @@ ;------------------------------------------------------------------------------ ; The SER API version, stored SER_HDR::VERSION -SER_API_VERSION = $01 +SER_API_VERSION = $02 ;------------------------------------------------------------------------------ ; ser_params diff --git a/asminc/tgi-kernel.inc b/asminc/tgi-kernel.inc index 6e687315d..e9f2f6aa9 100644 --- a/asminc/tgi-kernel.inc +++ b/asminc/tgi-kernel.inc @@ -77,7 +77,7 @@ ;------------------------------------------------------------------------------ ; The TGI API version, stored at TGI_HDR_VERSION -TGI_API_VERSION = $04 +TGI_API_VERSION = $05 ;------------------------------------------------------------------------------ ; Bitmapped tgi driver flags, stored in TGI_HDR::VARS::FLAGS. diff --git a/asminc/vic20.inc b/asminc/vic20.inc index 6780d067d..c42db4258 100644 --- a/asminc/vic20.inc +++ b/asminc/vic20.inc @@ -6,6 +6,7 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +TXTPTR := $7A ; Pointer into BASIC source code TIME := $A0 ; 60HZ clock FNAM_LEN := $B7 ; Length of filename SECADR := $B9 ; Secondary address diff --git a/cfg/atari-asm.cfg b/cfg/atari-asm.cfg new file mode 100644 index 000000000..4e87a8884 --- /dev/null +++ b/cfg/atari-asm.cfg @@ -0,0 +1,29 @@ +FEATURES { + STARTADDRESS: default = $2E00; +} +SYMBOLS { + __EXEHDR__: type = import; + __AUTOSTART__: type = import; # force inclusion of autostart "trailer" + __STARTADDRESS__: type = export, value = %S; +} +MEMORY { + ZP: file = "", define = yes, start = $0082, size = $007E; + +# file header, just $FFFF + HEADER: file = %O, start = $0000, size = $0002; + +# "main program" load chunk + MAINHDR: file = %O, start = $0000, size = $0004; + RAM: file = %O, define = yes, start = %S, size = $BC20 - %S; + TRAILER: file = %O, start = $0000, size = $0006; +} +SEGMENTS { + EXEHDR: load = HEADER, type = ro, optional = yes; + MAINHDR: load = MAINHDR, type = ro, optional = yes; + CODE: load = RAM, type = ro, define = yes, optional = yes; + RODATA: load = RAM, type = ro optional = yes; + DATA: load = RAM, type = rw optional = yes; + BSS: load = RAM, type = bss, define = yes, optional = yes; + ZEROPAGE: load = ZP, type = zp; + AUTOSTRT: load = TRAILER, type = ro, optional = yes; +} diff --git a/cfg/atari-overlay.cfg b/cfg/atari-overlay.cfg index 02becd29b..1d339b208 100644 --- a/cfg/atari-overlay.cfg +++ b/cfg/atari-overlay.cfg @@ -1,48 +1,67 @@ FEATURES { - STARTADDRESS: default = $2E00; + STARTADDRESS: default = $2000; } SYMBOLS { + __EXEHDR__: type = import; + __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk + __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay + __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = weak, value = $0000; } 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; + +# file header, 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; + +# "main program" load chunk + MAINHDR: file = %O, start = $0000, size = $0004; + RAM: file = %O, define = yes, start = %S + __OVERLAYSIZE__, + size = $BC20 - __OVERLAYSIZE__ - __STACKSIZE__ - __RESERVED_MEMORY__ - %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__; } 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; + 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, diff --git a/cfg/atari.cfg b/cfg/atari.cfg index a82f64f74..dce593f05 100644 --- a/cfg/atari.cfg +++ b/cfg/atari.cfg @@ -1,28 +1,46 @@ FEATURES { - STARTADDRESS: default = $2E00; + STARTADDRESS: default = $2000; } SYMBOLS { + __EXEHDR__: type = import; + __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk + __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack + __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = weak, value = $0000; } 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; + +# file header, 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; + +# "main program" load chunk + MAINHDR: file = %O, start = $0000, size = $0004; + RAM: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; + TRAILER: file = %O, start = $0000, size = $0006; } 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; + 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, diff --git a/cfg/atarixl-largehimem.cfg b/cfg/atarixl-largehimem.cfg new file mode 100644 index 000000000..01fc76a26 --- /dev/null +++ b/cfg/atarixl-largehimem.cfg @@ -0,0 +1,92 @@ +# 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 { + __EXEHDR__: type = import; + __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk + __AUTOSTART__: type = import; # force inclusion of autostart "trailer" + __STACKSIZE__: type = weak, value = $0800; # 2k stack + __STARTADDRESS__: type = export, value = %S; +} + +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 + + __LOWBSS_SIZE__, size = $D000 - + __STACKSIZE__ - + %S - + __LOWBSS_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 = $FFFA - $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; + LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized + 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__; +} diff --git a/cfg/atarixl-overlay.cfg b/cfg/atarixl-overlay.cfg index 02becd29b..68d0f524e 100644 --- a/cfg/atarixl-overlay.cfg +++ b/cfg/atarixl-overlay.cfg @@ -1,48 +1,101 @@ FEATURES { - STARTADDRESS: default = $2E00; + STARTADDRESS: default = $2400; } + SYMBOLS { + __EXEHDR__: type = import; + __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk + __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __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; } + 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__ + + __LOWBSS_SIZE__, size = $D000 - + __STACKSIZE__ - + %S - + __OVERLAYSIZE__ - + __LOWBSS_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 = $FFFA - $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; + LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized + 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, diff --git a/cfg/atarixl.cfg b/cfg/atarixl.cfg index a82f64f74..aad3ce613 100644 --- a/cfg/atarixl.cfg +++ b/cfg/atarixl.cfg @@ -1,28 +1,77 @@ FEATURES { - STARTADDRESS: default = $2E00; + STARTADDRESS: default = $2400; } + SYMBOLS { + __EXEHDR__: type = import; + __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk + __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack - __RESERVED_MEMORY__: type = weak, value = $0000; + __STARTADDRESS__: type = export, value = %S; } + 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 + + __LOWBSS_SIZE__, size = $D000 - + __STACKSIZE__ - + %S - + __LOWBSS_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 = $FFFA - $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; + LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized + 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, diff --git a/cfg/geos-apple.cfg b/cfg/geos-apple.cfg index 1900c4866..746e1f2bf 100644 --- a/cfg/geos-apple.cfg +++ b/cfg/geos-apple.cfg @@ -32,7 +32,7 @@ MEMORY { } SEGMENTS { ZEROPAGE: type = zp, load = ZP; - EXTZP: type = zp, load = ZP; + EXTZP: type = zp, load = ZP, optional = yes; EXTBSS: type = bss, load = EXT, define = yes, optional = yes; FILEINFO: type = ro, load = CVT, offset = $002; RECORDS: type = ro, load = CVT, offset = $100, optional = yes; diff --git a/cfg/geos-cbm.cfg b/cfg/geos-cbm.cfg index f2aea55a2..ddef00a99 100644 --- a/cfg/geos-cbm.cfg +++ b/cfg/geos-cbm.cfg @@ -31,7 +31,7 @@ MEMORY { } SEGMENTS { ZEROPAGE: type = zp, load = ZP; - EXTZP: type = zp, load = ZP; + EXTZP: type = zp, load = ZP, optional = yes; DIRENTRY: type = ro, load = CVT, align = $FE; FILEINFO: type = ro, load = CVT, align = $FE; RECORDS: type = ro, load = CVT, align = $FE, optional = yes; diff --git a/include/apple2.h b/include/apple2.h index 190248b0d..310e697b1 100644 --- a/include/apple2.h +++ b/include/apple2.h @@ -136,10 +136,22 @@ extern unsigned char _dos_type; /* The file stream implementation and the POSIX I/O functions will use the - * following variables to determine the file type and the aux type to use. + * following variables to determine the file type, aux type and creation time + * stamp to use. */ -extern unsigned char _filetype; /* Default 6 */ -extern unsigned int _auxtype; /* Default 0 */ +extern unsigned char _filetype; /* Default: 6 */ +extern unsigned int _auxtype; /* Default: 0 */ +extern struct { + struct { + unsigned day :5; + unsigned mon :4; + unsigned year :7; + } createdate; /* Current date: 0 */ + struct { + unsigned char min; + unsigned char hour; + } createtime; /* Current time: 0 */ +} _datetime; /* The addresses of the static drivers */ #if !defined(__APPLE2ENH__) diff --git a/include/atari.h b/include/atari.h index e47d1ccea..ff23526ee 100644 --- a/include/atari.h +++ b/include/atari.h @@ -131,6 +131,24 @@ #define COLOR_LIGHTBLUE _gtia_mkcolor(HUE_BLUE,6) #define COLOR_GRAY3 _gtia_mkcolor(HUE_GREY,5) +/* TGI color defines */ +#define TGI_COLOR_BLACK COLOR_BLACK +#define TGI_COLOR_WHITE COLOR_WHITE +#define TGI_COLOR_RED COLOR_RED +#define TGI_COLOR_CYAN COLOR_CYAN +#define TGI_COLOR_VIOLET COLOR_VIOLET +#define TGI_COLOR_GREEN COLOR_GREEN +#define TGI_COLOR_BLUE COLOR_BLUE +#define TGI_COLOR_YELLOW COLOR_YELLOW +#define TGI_COLOR_ORANGE COLOR_ORANGE +#define TGI_COLOR_BROWN COLOR_BROWN +#define TGI_COLOR_LIGHTRED COLOR_LIGHTRED +#define TGI_COLOR_GRAY1 COLOR_GRAY1 +#define TGI_COLOR_GRAY2 COLOR_GRAY2 +#define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN +#define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE +#define TGI_COLOR_GRAY3 COLOR_GRAY3 + /* color register functions */ extern void __fastcall__ _setcolor (unsigned char color_reg, unsigned char hue, unsigned char luminace); extern void __fastcall__ _setcolor_low (unsigned char color_reg, unsigned char color_value); @@ -268,5 +286,30 @@ struct __iocb { #define ZIOCB (*(struct __iocb *)0x20) /* zero page IOCB */ #define IOCB (*(struct __iocb *)0x340) /* system IOCB buffers */ +/* IOCB Command Codes */ +#define IOCB_OPEN 0x03 /* open */ +#define IOCB_GETREC 0x05 /* get record */ +#define IOCB_GETCHR 0x07 /* get character(s) */ +#define IOCB_PUTREC 0x09 /* put record */ +#define IOCB_PUTCHR 0x0B /* put character(s) */ +#define IOCB_CLOSE 0x0C /* close */ +#define IOCB_STATIS 0x0D /* status */ +#define IOCB_SPECIL 0x0E /* special */ +#define IOCB_DRAWLN 0x11 /* draw line */ +#define IOCB_FILLIN 0x12 /* draw line with right fill */ +#define IOCB_RENAME 0x20 /* rename disk file */ +#define IOCB_DELETE 0x21 /* delete disk file */ +#define IOCB_LOCKFL 0x23 /* lock file (set to read-only) */ +#define IOCB_UNLOCK 0x24 /* unlock file */ +#define IOCB_POINT 0x25 /* point sector */ +#define IOCB_NOTE 0x26 /* note sector */ +#define IOCB_GETFL 0x27 /* get file length */ +#define IOCB_CHDIR_MYDOS 0x29 /* change directory (MyDOS) */ +#define IOCB_MKDIR 0x2A /* make directory (MyDOS/SpartaDOS) */ +#define IOCB_RMDIR 0x2B /* remove directory (SpartaDOS) */ +#define IOCB_CHDIR_SPDOS 0x2C /* change directory (SpartaDOS) */ +#define IOCB_GETCWD 0x30 /* get current directory (MyDOS/SpartaDOS) */ +#define IOCB_FORMAT 0xFE /* format */ + /* End of atari.h */ #endif /* #ifndef _ATARI_H */ diff --git a/include/atmos.h b/include/atmos.h index eed6d7564..72388c974 100644 --- a/include/atmos.h +++ b/include/atmos.h @@ -126,12 +126,36 @@ extern void atmos_240_200_2_tgi[]; /* Referred to by tgi_static_stddrv[] */ +/*****************************************************************************/ +/* Functions */ +/*****************************************************************************/ + + + void __fastcall__ atmos_load(const char* name); /* Load Atmos tape. */ void __fastcall__ atmos_save(const char* name, const void* start, const void* end); /* Save Atmos tape. */ +void atmos_explode (void); +/* Bomb sound effect */ + +void atmos_ping (void); +/* Bell or ricochet sound effect */ + +void atmos_shoot (void); +/* Pistol sound effect */ + +void atmos_tick (void); +/* High-pitch click */ + +void atmos_tock (void); +/* Low-pitch click */ + +void atmos_zap (void); +/* Raygun sound effect */ + /* End of atmos.h */ diff --git a/include/cbm510.h b/include/cbm510.h index 350527c89..25ea07540 100644 --- a/include/cbm510.h +++ b/include/cbm510.h @@ -2,11 +2,11 @@ /* */ /* cbm510.h */ /* */ -/* System specific definitions for the CBM5x0 / P500 */ +/* System-specific definitions for the CBM5x0 / P500 */ /* */ /* */ /* */ -/* (C) 2001-2009, Ullrich von Bassewitz */ +/* (C) 2001-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -100,7 +100,7 @@ #define SID (*(struct __sid*)0xDA00) #include <_6526.h> -#define CIA (*(struct __6526*)0xDC00) +#define CIA2 (*(struct __6526*)0xDC00) #include <_6551.h> #define ACIA (*(struct __6551*)0xDD00) @@ -118,6 +118,8 @@ /* The addresses of the static drivers */ +extern void cbm510_inkwl_mou[]; +extern void cbm510_joy_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void cbm510_ram_emd[]; extern void cbm510_std_joy[]; /* Referred to by joy_static_stddrv[] */ extern void cbm510_std_ser[]; diff --git a/libsrc/apple2/open.s b/libsrc/apple2/open.s index db40c3c74..b1686df70 100644 --- a/libsrc/apple2/open.s +++ b/libsrc/apple2/open.s @@ -5,7 +5,7 @@ ; .export _open, closedirect, freebuffer - .export __filetype, __auxtype + .export __filetype, __auxtype, __datetime .constructor raisefilelevel .destructor closeallfiles, 5 @@ -246,5 +246,6 @@ __filetype: __auxtype: .word $0000 ; AUX_TYPE: Load address N/A .byte $01 ; STORAGE_TYPE: Standard seedling file +__datetime: .word $0000 ; CREATE_DATE: Current date .word $0000 ; CREATE_TIME: Current time diff --git a/libsrc/atari/Makefile.inc b/libsrc/atari/Makefile.inc index d12b54058..af5a17e59 100644 --- a/libsrc/atari/Makefile.inc +++ b/libsrc/atari/Makefile.inc @@ -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 diff --git a/libsrc/atari/_sys.s b/libsrc/atari/_sys.s new file mode 100644 index 000000000..66e4905ec --- /dev/null +++ b/libsrc/atari/_sys.s @@ -0,0 +1,13 @@ +; +; Christian Groessler, 17-Sep-2013 +; +; Override _sys() function for Atari targets: +; 'atari' gets the regular function +; 'atarixl' doesn't support the _sys() function +; + +.ifndef __ATARIXL__ + +.include "../common/_sys.s" + +.endif diff --git a/libsrc/atari/cgetc.s b/libsrc/atari/cgetc.s index f8948a5bc..54fe85bb4 100644 --- a/libsrc/atari/cgetc.s +++ b/libsrc/atari/cgetc.s @@ -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 diff --git a/libsrc/atari/crt0.s b/libsrc/atari/crt0.s index 85a3ffcde..fb434b5de 100644 --- a/libsrc/atari/crt0.s +++ b/libsrc/atari/crt0.s @@ -8,28 +8,26 @@ ; Stefan Haubenthal ; - .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup + .export _exit, start .import initlib, donelib .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 + .forceimport sramprep ; force inclusion of the "shadow RAM preparation" load chunk + .include "save_area.inc" +.endif .include "zeropage.inc" .include "atari.inc" ; ------------------------------------------------------------------------ -; EXE header - -.segment "EXEHDR" - - .word $FFFF - .word __STARTUP_LOAD__ - .word __BSS_LOAD__ - 1 - -; ------------------------------------------------------------------------ -; Actual code .segment "STARTUP" @@ -40,6 +38,12 @@ ; Real entry point: +start: + +.ifdef __ATARIXL__ + jsr sram_init +.endif + ; Clear the BSS data jsr zerobss @@ -47,14 +51,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 +72,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 +88,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 +113,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 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 +193,9 @@ _exit: jsr donelib ; Run module destructors .bss -spsave: .res 1 -appmsav: .res 1 -old_shflok: .res 1 -old_lmargin: .res 1 - - -.segment "AUTOSTRT" - .word RUNAD ; defined in atari.inc - .word RUNAD+1 - .word __STARTUP_LOAD__ + 1 +SP_save: .res 1 +SHFLOK_save: .res 1 +LMARGN_save: .res 1 +.ifndef __ATARIXL__ +APPMHI_save: .res 2 +.endif diff --git a/libsrc/atari/exehdr.s b/libsrc/atari/exehdr.s new file mode 100644 index 000000000..ea9fa95d7 --- /dev/null +++ b/libsrc/atari/exehdr.s @@ -0,0 +1,11 @@ +; This file defines the EXE header and main chunk load header for Atari executables + + .export __EXEHDR__: absolute = 1 + .import __RAM_START__, __BSS_LOAD__ + +.segment "EXEHDR" + .word $FFFF + +.segment "MAINHDR" + .word __RAM_START__ + .word __BSS_LOAD__ - 1 diff --git a/libsrc/atari/exetrailer.s b/libsrc/atari/exetrailer.s new file mode 100644 index 000000000..8cae0bdf0 --- /dev/null +++ b/libsrc/atari/exetrailer.s @@ -0,0 +1,12 @@ +; This file defines the EXE file "trailer" which sets the entry point + + .export __AUTOSTART__: absolute = 1 + .import start + + .include "atari.inc" + +.segment "AUTOSTRT" + .word RUNAD ; defined in atari.inc + .word RUNAD+1 + .word start + diff --git a/libsrc/atari/graphics.s b/libsrc/atari/graphics.s index 1c6856296..ab26ed0da 100644 --- a/libsrc/atari/graphics.s +++ b/libsrc/atari/graphics.s @@ -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 diff --git a/libsrc/atari/irq.s b/libsrc/atari/irq.s index 9a433ca00..8ec1b12df 100644 --- a/libsrc/atari/irq.s +++ b/libsrc/atari/irq.s @@ -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 ; ------------------------------------------------------------------------ diff --git a/libsrc/atari/libref.s b/libsrc/atari/libref.s index 8d9ff3e08..171bd6de6 100644 --- a/libsrc/atari/libref.s +++ b/libsrc/atari/libref.s @@ -7,4 +7,9 @@ em_libref := _exit joy_libref := _exit +.ifdef __ATARIXL__ + .import CIO_handler +tgi_libref := CIO_handler +.else tgi_libref := _exit +.endif diff --git a/libsrc/atari/ostype.s b/libsrc/atari/ostype.s index d93b3ab88..7248582a6 100644 --- a/libsrc/atari/ostype.s +++ b/libsrc/atari/ostype.s @@ -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 diff --git a/libsrc/atari/romswitch.inc b/libsrc/atari/romswitch.inc new file mode 100644 index 000000000..ed4cd96d8 --- /dev/null +++ b/libsrc/atari/romswitch.inc @@ -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 ; above CHARGEN_RELOC, below not + +.macro set_chbase val +.endmacro + +.endif ; .ifdef CHARGEN_RELOC + + +.if .defined(USEWSYNC) .and .defined(CHARGEN_RELOC) + +.macro wsync + sta WSYNC +.endmacro + +.else ; above USEWSYNC, below not + +.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 diff --git a/libsrc/atari/save_area.inc b/libsrc/atari/save_area.inc new file mode 100644 index 000000000..ac433fded --- /dev/null +++ b/libsrc/atari/save_area.inc @@ -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 diff --git a/libsrc/atari/save_area.s b/libsrc/atari/save_area.s new file mode 100644 index 000000000..8e6b13369 --- /dev/null +++ b/libsrc/atari/save_area.s @@ -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 "LOWBSS" + +SAVMSC_save: .res 2 +MEMTOP_save: .res 2 +APPMHI_save: .res 2 +RAMTOP_save: .res 1 +PORTB_save: .res 1 + +.endif diff --git a/libsrc/atari/scrdev.s b/libsrc/atari/scrdev.s new file mode 100644 index 000000000..2d6ff3e07 --- /dev/null +++ b/libsrc/atari/scrdev.s @@ -0,0 +1,7 @@ +; Name of the "screen" device + + .export scrdev + + .rodata + +scrdev: .byte "S:", 0 diff --git a/libsrc/atari/shadow_ram_handlers.s b/libsrc/atari/shadow_ram_handlers.s new file mode 100644 index 000000000..53a71ab71 --- /dev/null +++ b/libsrc/atari/shadow_ram_handlers.s @@ -0,0 +1,1101 @@ +; +; Atari XL shadow RAM handlers +; +; Christian Groessler, chris@groessler.org, 2013 +; + +;DEBUG = 1 +CHKBUF = 1 ; check if bounce buffering is needed (bounce buffering is always done if set to 0) + +.ifdef __ATARIXL__ + +SHRAM_HANDLERS = 1 + .include "atari.inc" + .include "save_area.inc" + .include "zeropage.inc" + .include "romswitch.inc" + + .import __CHARGEN_START__ + + .export sram_init + .export KEYBDV_handler + .export CIO_handler + .export SIO_handler + .export SETVBV_handler + +BUFSZ = 128 ; bounce buffer size +BUFSZ_SIO = 256 + +.segment "INIT" + +; Turn off ROMs, install system and interrupt wrappers, set new chargen pointer + +sram_init: + +; disable all interrupts + ldx #0 + stx NMIEN ; disable NMI + sei + +; disable ROMs + disable_rom + +; setup interrupt vectors + lda #my_IRQ_han + sta $ffff + + lda #my_RESET_han + sta $fffd + + lda #my_NMI_han + sta $fffb + +; enable interrupts + cli + lda #$40 + sta NMIEN + + rts + +.segment "EXTZP" : zeropage + +zpptr1: .res 2 + + +.segment "LOWBSS" + +; bounce buffers for CIO and SIO calls +bounce_buffer: .res BUFSZ_SIO + + +.segment "LOWCODE" + + +; Interrupt handlers +; ------------------ + +; The interrupt handlers don't look at the current state of PORTB and +; unconditionally disable the ROMs on exit. +; Please note that this works, since if the ROMs are enabled we anyway +; aren't being called here because the vectors are pointing to their +; original ROM locations. + +.macro int_wrap orgvec + .local ret + pha + enable_rom_quick + lda #>ret + pha + lda # data too large for our buffers + ; CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES + lda # bounce buffer size? + bcs br_last ; no, last transfer, use remaining size + + lda #>BUFSZ + sta ICBLH,x ; set data length + lda # data too large for our buffers + ; CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES + lda # bounce buffer size? + bcs bw_last ; no, last transfer, use remaining size + + lda #>BUFSZ + sta ICBLH,x ; set data length + lda #BUFSZ + sbc orig_len+1 + rts + + +; copy data from bounce buffer into user buffer +; input: X - IOCB index +; zpptr1 - pointer to user buffer +; output: A - destroyed +; Y - 0 +copy_to_user: + ldy ICBLL,x ; get # of bytes read (CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES) + beq @copy_done +@copy: dey + lda bounce_buffer,y + sta (zpptr1),y + cpy #0 + bne @copy +@copy_done: + rts + + +; copy data from user buffer into bounce buffer +; input: X - IOCB index +; zpptr1 - pointer to user buffer +; output: A - destroyed +; Y - 0 +copy_from_user: + ldy ICBLL,x ; get # of bytes to write (CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES) + beq @copy_done +@copy: dey + lda (zpptr1),y + sta bounce_buffer,y + cpy #0 + bne @copy +@copy_done: + rts + + +; copy ICBLL/ICBLH to 'orig_len' +; input: X - IOCB index +; output: A - destroyed +iocblen_to_orig_len: + lda ICBLL,x + sta orig_len + lda ICBLH,x + sta orig_len+1 + rts + + +; copy ICBAL/ICBAH to 'orig_ptr' +; input: X - IOCB index +; output: A - destroyed +iocbptr_to_orig_ptr: + lda ICBAL,x + sta orig_ptr + lda ICBAH,x + sta orig_ptr+1 + rts + + +; copy 'orig_ptr' to ICBAL/ICBAH +; input: X - IOCB index +; output: A - destroyed +orig_ptr_to_iocbptr: + lda orig_ptr + sta ICBAL,x + lda orig_ptr+1 + sta ICBAH,x + rts + + +; restore original contents of ICBAL/ICBAH from 'zpptr1' +; input: X - IOCB index +; output: A - destroyed +restore_icba: + lda zpptr1 + sta ICBAL,x + lda zpptr1+1 + sta ICBAH,x + rts + + +; put bounce buffer address into ICBAL/ICBAH +; input: X - IOCB index +; output: A - destroyed +bncbuf_to_iocb: + lda #bounce_buffer + sta ICBAH,x + rts + + +; copy file name pointed to by 'zpptr1' to 'bounce_buffer' +; input: Y - index into file name buffer and bounce_buffer +; output: Y - points to first invalid byte after file name +; A - destroyed +copy_filename: + lda (zpptr1),y + sta bounce_buffer,y + beq copy_fn_done + iny + cmp #ATEOL + bne copy_filename + dey +copy_fn_done: + rts + + +; write IOCB buffer address into zpptr1 +; input: X - IOCB index +; output: Y - 0 (for setup_zpptr1_y0, else unchanged) +; A - destroyed +setup_zpptr1_y0: + ldy #0 +setup_zpptr1: + lda ICBAL,x ; put buffer address into zp pointer + sta zpptr1 + lda ICBAH,x + sta zpptr1+1 + rts + + +.if CHKBUF + +; get length of file name pointed to by 'zpptr1' +; input: Y - index into file name +; output: Y - length +; A - destroyed +get_fn_len: + lda (zpptr1),y + beq @done + iny + cmp #ATEOL + bne get_fn_len + dey +@done: + rts + + +chk_CIO_buf_fn2: + tya + pha + lda ICBLL,x + pha + lda ICBLH,x + pha + jsr setup_zpptr1_y0 + jsr get_fn_len + iny ; include terminating zero + bne fn_cont + +chk_CIO_buf_fn: + tya + pha + lda ICBLL,x + pha + lda ICBLH,x + pha + jsr setup_zpptr1_y0 +fn_cont:jsr get_fn_len + iny ; include terminating zero + tya + sta ICBLL,x + lda #0 + sta ICBLH,x + jsr chk_CIO_buf + pla + sta ICBLH,x + pla + sta ICBLL,x + pla + tay + rts + + +; check if a CIO input/output buffer overlaps with ROM area (>= $C000) +; input: X - IOCB index +; ICBAL/ICBAH/ICBLL/ICBLH - buffer address and length +; output: CF - 1/0 for overlap/no overlap +; A - destroyed + +chk_CIO_buf: + lda ICBAH,x + cmp #$c0 + bcc @cont +@ret: +.ifdef DEBUG + jsr CIO_buf_noti +.endif + rts + +@cont: lda ICBAL,x + clc + adc ICBLL,x + lda ICBAH,x + adc ICBLH,x + bcs @ret ; ??? wraparound + cmp #$c0 +.ifdef DEBUG + jsr CIO_buf_noti +.endif + rts + +.ifdef DEBUG +; write to screen memory on 2nd line: +; pos 0: # of accesses without buffering +; pos 1: # of accesses with buffering +CIO_buf_noti: + php + pha + tya + pha + bcc @nobuf + + inc CIObnval_dobuf + jmp @cont + +@nobuf: inc CIObnval_nobuf + +@cont: ldy #40 + lda CIObnval_nobuf + sta (SAVMSC),y + ldy #41 + lda CIObnval_dobuf + sta (SAVMSC),y + + pla + tay + pla + plp + rts + +CIObnval_dobuf: + .byte 0 +CIObnval_nobuf: + .byte 0 +.endif + +.endif ; .if CHKBUF + +;--------------------------------------------------------- + +; SIO handler +; We only handle SIO_STAT, SIO_READ, SIO_WRITE, and SIO_WRITEV. +; These are the only functions used by the runtime library currently. +; For other function we return NVALID status code. + +SIO_handler: + lda DCOMND ; get command + cmp #SIO_STAT + beq SIO_stat + cmp #SIO_READ + beq SIO_read + cmp #SIO_WRITE + beq SIO_write + cmp #SIO_WRITEV + beq SIO_write + + ; unhandled command + lda #NVALID +SIO_err:sta DSTATS + rts + +; SIO_STAT is always called with a low buffer (by the runtime) +SIO_stat: + ; fall thru + +SIO_call: + lda PORTB + sta cur_SIOV_PORTB + enable_rom + jsr SIOV_org + php + pha + disable_rom_val cur_SIOV_PORTB + pla + plp + rts + + +; SIO read handler +; ---------------- + +SIO_read: + +.if CHKBUF + jsr chk_SIO_buf + bcc SIO_call +.endif + +; we only support transfers <= bounce buffer size + jsr cmp_sio_len_bnc_bufsz + bcs sio_read_len_ok + + lda #DERROR ; don't know a better status code for this + bne SIO_err + +sio_read_len_ok: + lda DBUFLO + sta zpptr1 ; remember destination buffer address + lda DBUFHI + sta zpptr1+1 + + jsr bncbuf_to_dbuf ; put bounce buffer address to DBUFLO/DBUFHI + + jsr SIO_call ; do the operation + pha + lda DSTATS ; get status + bmi sio_read_ret ; error + + ; copy data to user buffer +sio_read_ok: + lda DBYTHI ; could be 1 for 256 bytes + beq srok1 + ldy #0 + beq srok2 +srok1: ldy DBYTLO +srok2: dey +sio_read_copy: + lda bounce_buffer,y + sta (zpptr1),y + dey + cpy #$ff + bne sio_read_copy + +sio_read_ret: + jsr orgbuf_to_dbuf + + pla + rts ; success return + + +; SIO write handler +; ----------------- + +SIO_write: + +.if CHKBUF + jsr chk_SIO_buf + bcc SIO_call +.endif + +; we only support transfers <= bounce buffer size + jsr cmp_sio_len_bnc_bufsz + bcs sio_write_len_ok + + lda #DERROR ; don't know a better status code for this + jmp SIO_err + +sio_write_len_ok: + lda DBUFLO + sta zpptr1 ; get source buffer address + lda DBUFHI + sta zpptr1+1 + + ; copy data from user buffer to bounce buffer + lda DBYTHI ; could be 1 for 256 bytes + beq swok1 + ldy #0 + beq swok2 +swok1: ldy DBYTLO +swok2: dey +sio_write_copy: + lda (zpptr1),y + sta bounce_buffer,y + dey + cpy #$ff + bne sio_write_copy + + jsr bncbuf_to_dbuf ; put bounce buffer address to DBUFLO/DBUFHI + + jsr SIO_call ; do the operation + pha + jsr orgbuf_to_dbuf + pla + rts + + +; check if SIO length is larger than bounce buffer size +; input: orig_len - length +; output: A - destroyed +; CF - 0/1 for larger/not larger +cmp_sio_len_bnc_bufsz: + sec + lda #BUFSZ_SIO + sbc DBYTHI + rts + +; put bounce buffer address into DBUFLO/DBUFHI +; input: (--) +; output: A - destroyed +bncbuf_to_dbuf: + lda #bounce_buffer + sta DBUFHI + rts + +; put original buffer address into DBUFLO/DBUFHI +; input: zpptr1 - original pointer +; output: A - destroyed +orgbuf_to_dbuf: + lda zpptr1 + sta DBUFLO + lda zpptr1+1 + sta DBUFHI + rts + + +.if CHKBUF + +; check if a SIO input/output buffer overlaps with ROM area (>= $C000) +; input: DBUFLO/DBUFHI/DBYTLO/DBYTHI - buffer address and length +; output: CF - 1/0 for overlap/no overlap +; A - destroyed + +chk_SIO_buf: + lda DBUFHI + cmp #$c0 + bcc @cont +@ret: +.ifdef DEBUG + jsr SIO_buf_noti +.endif + rts + +@cont: lda DBUFLO + clc + adc DBYTLO + lda DBUFHI + adc DBYTHI + bcs @ret ; ??? wraparound + cmp #$c0 +.ifdef DEBUG + jsr SIO_buf_noti +.endif + rts + +.ifdef DEBUG +; write to screen memory on 2nd line: +; pos 38: # of accesses without buffering +; pos 39: # of accesses with buffering +SIO_buf_noti: + php + pha + tya + pha + bcc @nobuf + + inc SIObnval_dobuf + jmp @cont + +@nobuf: inc SIObnval_nobuf + +@cont: ldy #78 + lda SIObnval_nobuf + sta (SAVMSC),y + ldy #79 + lda SIObnval_dobuf + sta (SAVMSC),y + + pla + tay + pla + plp + rts + +SIObnval_dobuf: + .byte 0 +SIObnval_nobuf: + .byte 0 +.endif + +.endif ; .if CHKBUF + +;--------------------------------------------------------- + +KEYBDV_handler: + + lda #>(kret-1) + pha + lda #<(kret-1) + pha + lda PORTB + sta cur_KEYBDV_PORTB + enable_rom + lda KEYBDV+5 + pha + lda KEYBDV+4 + pha + rts ; call keyboard handler +kret: pha + disable_rom_val cur_KEYBDV_PORTB + pla + rts + +;--------------------------------------------------------- + +SETVBV_handler: + + pha + lda PORTB + sta cur_SETVBV_PORTB + enable_rom + pla + jsr SETVBV_org + php + pha + disable_rom_val cur_SETVBV_PORTB + pla + plp + rts + +CIO_a: .res 1 +CIO_x: .res 1 +CIO_y: .res 1 +CIO_p: .res 1 +cur_CIOV_PORTB: .res 1 +cur_SIOV_PORTB: .res 1 +cur_KEYBDV_PORTB: .res 1 +cur_SETVBV_PORTB: .res 1 +orig_ptr: .res 2 +orig_len: .res 2 +req_len: .res 2 +retlen: .res 2 + +.endif ; .ifdef __ATARIXL__ diff --git a/libsrc/atari/shadow_ram_prepare.s b/libsrc/atari/shadow_ram_prepare.s new file mode 100644 index 000000000..a1760bd72 --- /dev/null +++ b/libsrc/atari/shadow_ram_prepare.s @@ -0,0 +1,408 @@ +; +; 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 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" + +; ***** entry point ***** + +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 ICBAH,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+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 #2 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__ diff --git a/libsrc/atari/sysrmdir.s b/libsrc/atari/sysrmdir.s index 126c11cca..3f5b9e447 100644 --- a/libsrc/atari/sysrmdir.s +++ b/libsrc/atari/sysrmdir.s @@ -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 diff --git a/libsrc/atari/system_check.s b/libsrc/atari/system_check.s new file mode 100644 index 000000000..dbc0b5dfb --- /dev/null +++ b/libsrc/atari/system_check.s @@ -0,0 +1,215 @@ +; +; 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 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 ICBAH,x + lda #len + sta ICBLH,x + lda #PUTCHR + sta ICCOM,x + jsr CIOV_org +.endmacro + + +; ------------------------------------------------------------------------ +; code + +.segment "SYSCHK" + +.ifdef __ATARIXL__ + +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: + .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 diff --git a/libsrc/atari/tgi/atari_tgi_common.inc b/libsrc/atari/tgi/atari_tgi_common.inc index 7dba884fa..0d7972d34 100644 --- a/libsrc/atari/tgi/atari_tgi_common.inc +++ b/libsrc/atari/tgi/atari_tgi_common.inc @@ -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 diff --git a/libsrc/atari/xlmemchk.inc b/libsrc/atari/xlmemchk.inc new file mode 100644 index 000000000..f8be1c137 --- /dev/null +++ b/libsrc/atari/xlmemchk.inc @@ -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+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+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: diff --git a/libsrc/atmos/atmos.s b/libsrc/atmos/atmos.s new file mode 100644 index 000000000..6b5a4a49c --- /dev/null +++ b/libsrc/atmos/atmos.s @@ -0,0 +1,15 @@ +; +; Expose include-file symbol names to C code. +; + + .export _atmos_ping, _atmos_shoot, _atmos_explode + .export _atmos_zap, _atmos_tick, _atmos_tock + + .include "atmos.inc" + +_atmos_ping := PING +_atmos_shoot := SHOOT +_atmos_explode := EXPLODE +_atmos_zap := ZAP +_atmos_tick := TICK +_atmos_tock := TOCK diff --git a/libsrc/c128/libref.s b/libsrc/c128/libref.s index 4f65e3959..7a59236c5 100644 --- a/libsrc/c128/libref.s +++ b/libsrc/c128/libref.s @@ -5,7 +5,6 @@ .export em_libref .export joy_libref -; .export mouse_libref .export ser_libref .export tgi_libref @@ -13,6 +12,5 @@ em_libref := _exit joy_libref := _exit -;mouse_libref := _exit ser_libref := _exit tgi_libref := _exit diff --git a/libsrc/c64/libref.s b/libsrc/c64/libref.s index 4f65e3959..7a59236c5 100644 --- a/libsrc/c64/libref.s +++ b/libsrc/c64/libref.s @@ -5,7 +5,6 @@ .export em_libref .export joy_libref -; .export mouse_libref .export ser_libref .export tgi_libref @@ -13,6 +12,5 @@ em_libref := _exit joy_libref := _exit -;mouse_libref := _exit ser_libref := _exit tgi_libref := _exit diff --git a/libsrc/cbm/exec.c b/libsrc/cbm/exec.c new file mode 100644 index 000000000..36c3afe00 --- /dev/null +++ b/libsrc/cbm/exec.c @@ -0,0 +1,118 @@ +/* +** Program-chaining function for Commodore platforms. +** +** 2013-09-04, Greg King +** +** This function exploits the program-chaining feature in CBM BASIC's ROM. +** +** CC65's CBM programs have a BASIC program stub. We start those programs by +** RUNning that stub; it SYSes to the Machine Language code. Normally, after +** the ML code exits, the BASIC ROM continues running the stub. But, it has +** no more statements; so, the program stops. +** +** This function puts the desired program's name and device number into a LOAD +** statement. Then, it points BASIC to that statement, so that the ROM will run +** that statement after this program quits. The ROM will load the next program, +** and will execute it (because the LOAD will be seen in a running program). +*/ + +#include +#include +#include +#include +#include +#include +#if defined(__CBM610__) +# include +#elif defined(__CBM510__) +# include +#endif + + +/* The struct below is a line of BASIC code. It sits in the LOWCODE segment +** to make sure that it won't be hidden by a ROM when BASIC is re-enabled. +** The line is: +** 0 LOAD""+"" ,01 +** After this function has written into the line, it might look like this: +** 0 LOAD""+"program name" ,08 +** +** When BASIC's LOAD command asks the Kernal to load a file, it gives the +** Kernal a pointer to a file-name string. CC65's CBM programs use that +** pointer to give a copy of the program's name to main()'s argv[0] parameter. +** But, when BASIC uses a string literal that's in a program, it points +** directly to that literal -- in the models that don't use banked RAM +** (Pet/CBM, VIC-20, and 64). The literal is overwritten by the next program +** that's loaded. So, argv[0] would point to machine code. String operations +** create a new result string -- even when that operation changes nothing. The +** result is put in the string space at the top of BASIC's memory. So, the ""+ +** in this BASIC line guarantees that argv[0] will get a name from a safe place. +*/ +#pragma data-name(push, "LOWCODE") +static struct line { + const char end_of_line; + const struct line *const next; + const unsigned line_num; + const char load_token, quotes[2], add_token, quote; + char name[21]; + const char comma; + char unit[3]; +} basic = { + '\0', &basic + 1, /* high byte of link must be non-zero */ + 0, 0x93, "\"\"", 0xaa, '\"', + "\" ", /* format: "123:1234567890123456\"" */ + ',', "01" +}; +#pragma data-name(pop) + +/* These values are platform-specific. */ +extern const struct line *txtptr; +#pragma zpsym("txtptr") +extern char basbuf[]; /* BASIC's input buffer */ +extern void basbuf_len[]; +#pragma zpsym("basbuf_len") + + +int __fastcall__ exec (const char* progname, const char* cmdline) +{ + static int fd; + static unsigned char dv, n = 0; + + /* Exclude devices that can't load files. */ + dv = getcurrentdevice (); + if (dv < 8 && dv != 1 || dv > 30) { + return _mappederrno (9); /* illegal device number */ + } + utoa (dv, basic.unit, 10); + + /* Don't try to run a program that can't be found. */ + fd = open (progname, O_RDONLY); + if (fd < 0) { + return fd; + } + close (fd); + + do { + if ((basic.name[n] = progname[n]) == '\0') { + break; + } + } while (++n < 20); /* truncate long names */ + basic.name[n] = '\"'; + + /* Build the next program's argument list. */ + basbuf[0] = 0x8f; /* REM token */ + basbuf[1] = '\0'; + if (cmdline != NULL) { + strncat (basbuf, cmdline, (size_t)basbuf_len - 2); + } + +#if defined(__CBM510__) || defined(__CBM610__) + pokewsys ((unsigned)&txtptr, (unsigned)&basic); +#else + txtptr = &basic; +#endif + + /* (The return code, in ST, will be destroyed by LOAD. + ** So, don't bother to set it here.) + */ + exit (__AX__); +} diff --git a/libsrc/cbm/execvars.s b/libsrc/cbm/execvars.s new file mode 100644 index 000000000..02eabc12e --- /dev/null +++ b/libsrc/cbm/execvars.s @@ -0,0 +1,28 @@ +; +; Platform-specific variables for the exec program-chaining function +; + +.if .defined (__C128__) + .include "c128.inc" +.elseif .defined (__C16__) + .include "c16.inc" +.elseif .defined (__C64__) + .include "c64.inc" +.elseif .defined (__CBM510__) + .include "cbm510.inc" +.elseif .defined (__CBM610__) + .include "cbm610.inc" +.elseif .defined (__PET__) + .include "pet.inc" +.elseif .defined (__PLUS4__) + .include "plus4.inc" +.else + .include "vic20.inc" +.endif + + .export _txtptr:zp, _basbuf, _basbuf_len:zp + +_txtptr := TXTPTR + +_basbuf := BASIC_BUF +_basbuf_len = BASIC_BUF_LEN diff --git a/libsrc/cbm510/crt0.s b/libsrc/cbm510/crt0.s index 871fbb850..836038a06 100644 --- a/libsrc/cbm510/crt0.s +++ b/libsrc/cbm510/crt0.s @@ -56,9 +56,9 @@ ;------------------------------------------------------------------------------ ; A table that contains values that must be transfered from the system zero -; page into out zero page. Contains pairs of bytes, first one is the address +; page into our zero page. Contains pairs of bytes; first one is the address ; in the system ZP, second one is our ZP address. The table goes into page 2, -; but is declared here, because it is needed earlier. +; but is declared here because it is needed earlier. .SEGMENT "PAGE2" @@ -67,6 +67,8 @@ .byte $9F, DEVNUM .byte $CA, CURS_Y .byte $CB, CURS_X + .byte $E6, CURS_FLAG + .byte $E7, CURS_BLINK .byte $EC, CHARCOLOR .endproc diff --git a/libsrc/cbm510/mcbdefault.s b/libsrc/cbm510/mcbdefault.s new file mode 100644 index 000000000..a6504ae30 --- /dev/null +++ b/libsrc/cbm510/mcbdefault.s @@ -0,0 +1,131 @@ +; +; Default mouse callbacks for the CBM510 (P128) +; +; 2004-03-20, Ullrich von Bassewitz2 +; 2013-06-25, Greg King +; +; All functions in this module should be interrupt-safe because they might +; be called from an interrupt handler. +; + + .export _mouse_def_callbacks + .import vic:zp + + .include "mouse-kernel.inc" + .include "cbm510.inc" + + .macpack generic + +; Sprite definitions. The first value can be changed to adjust the number +; of the sprite used for the mouse. All others depend on that value. +MOUSE_SPR = 0 ; Sprite used for the mouse +MOUSE_SPR_MASK = $01 .shl MOUSE_SPR ; Positive mask +MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask +VIC_SPR_X = (VIC_SPR0_X + 2*MOUSE_SPR) ; Sprite X register +VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register + +; -------------------------------------------------------------------------- +; Hide the mouse pointer. Always called with interrupts disabled. + +.proc hide + + ldy #15 + sty IndReg + + ldy #VIC_SPR_ENA + lda (vic),y + and #MOUSE_SPR_NMASK + sta (vic),y + + ldy ExecReg + sty IndReg + rts + +.endproc + +; -------------------------------------------------------------------------- +; Show the mouse pointer. Always called with interrupts disabled. + +.proc show + + ldy #15 + sty IndReg + + ldy #VIC_SPR_ENA + lda (vic),y + ora #MOUSE_SPR_MASK + sta (vic),y + + ldy ExecReg + sty IndReg + rts + +.endproc + +; -------------------------------------------------------------------------- +; Move the mouse pointer x position to the value in .XA. Always called with +; interrupts disabled. + +.proc movex + + ldy #15 + sty IndReg + +; Add the x correction; and, set the low byte. That frees .A. + + add #<24 ; x correction + ldy #VIC_SPR_X + sta (vic),y + +; Set the high byte + + ldy #VIC_SPR_HI_X + txa + adc #>24 + bnz @L1 ; Branch if high byte not zero + lda (vic),y ; Get high x bits of all sprites + and #MOUSE_SPR_NMASK ; Clear high bit for sprite + sta (vic),y + +@L0: ldy ExecReg + sty IndReg + rts + +@L1: lda (vic),y ; Get high x bits of all sprites + ora #MOUSE_SPR_MASK ; Set high bit for sprite + sta (vic),y + bnz @L0 ; branch always + +.endproc + +; -------------------------------------------------------------------------- +; Move the mouse pointer y position to the value in .XA. Always called with +; interrupts disabled. + +.proc movey + + ldy #15 + sty IndReg + + add #50 ; y correction (first visible line) + ldy #VIC_SPR_Y + sta (vic),y ; Set y position + + ldy ExecReg + sty IndReg + rts + +.endproc + +; -------------------------------------------------------------------------- +; Callback structure + +.rodata + +_mouse_def_callbacks: + .addr hide + .addr show + .addr movex + .addr movey + + diff --git a/libsrc/cbm510/mou/cbm510-inkwl.s b/libsrc/cbm510/mou/cbm510-inkwl.s new file mode 100644 index 000000000..8502a7034 --- /dev/null +++ b/libsrc/cbm510/mou/cbm510-inkwl.s @@ -0,0 +1,444 @@ +; +; Driver for the Inkwell Systems 170-C and 184-C lightpens. +; +; This driver reads only the main button on the 184-C. +; +; 2013-09-05, Greg King +; + + .include "zeropage.inc" + .include "../extzp.inc" + + .include "mouse-kernel.inc" + .include "cbm510.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Header. Includes jump table. + +.segment "JUMPTABLE" + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; ASCII "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + +LIBREF: .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_EARLY_IRQ + +; Callback table, set by the kernel before INSTALL is called. + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CMOVEX: jmp $0000 ; Move the cursor to X co-ord. +CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_WIDTH = XSIZE * 8 +SCREEN_HEIGHT = YSIZE * 8 + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines; so, don't +; re-order them. + +.rodata + +; Default values for below variables +; (We use ".proc" because we want to define both a label and a scope.) + +.proc DefVars + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax +.endproc + +.bss + +Vars: +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box + +XPos: .res 2 ; Current lightpen position, X +YPos: .res 2 ; Current lightpen position, Y + +OldPenX: .res 1 ; Previous HW-counter values +OldPenY: .res 1 + +.data + +; Default Inkwell calibration. +; The first number is the width of the left border; +; the second number is the actual calibration value. + +XOffset: .byte (24 + 24) / 2 ; x-offset + +; Jump to a function that puts a new calibration value into XOffset. +Calibrate: jmp $0000 + + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return a MOUSE_ERR_xx code in .XA. + +INSTALL: + +; Initiate variables. Just copy the default stuff over. + + ldx #.sizeof (DefVars) - 1 +@L0: lda DefVars,x + sta Vars,x + dex + bpl @L0 + + ldx #15 ; Change to system bank + stx IndReg + ldy #VIC_LPEN_X + lda (vic),y + sta OldPenX + ldy #VIC_LPEN_Y + lda (vic),y + sta OldPenY + ldx ExecReg ; Change back to execution bank + stx IndReg + +; Call a calibration function through the library-reference. + + lda LIBREF + ldx LIBREF+1 + sta ptr1 ; Point to mouse_adjuster + stx ptr1+1 + ldy #1 + lda (ptr1),y + bze @L1 ; Don't call pointer if it's NULL + sta Calibrate+2 ; Point to function + dey + lda (ptr1),y + sta Calibrate+1 + lda #XOffset + jsr Calibrate + +; Be sure that the lightpen cursor is invisible and at the default location. +; It needs to be done here because the lightpen interrupt handler doesn't +; set the lightpen position if it hasn't changed. + +@L1: sei + jsr CHIDE + + lda #<(SCREEN_HEIGHT / 2) + ldx #>(SCREEN_HEIGHT / 2) + jsr MoveY + lda #<(SCREEN_WIDTH / 2) + ldx #>(SCREEN_WIDTH / 2) + jsr MoveX + cli + +; Done, return zero. + + lda #MOUSE_ERR_OK + tax + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory on return). + +UNINSTALL := HIDE ; Hide cursor on exit + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the lightpen pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is called only +; if the mouse is currently visible, and should get hidden. For most drivers, +; no special action is required besides hiding the lightpen cursor. +; No return code required. + +HIDE: sei + jsr CHIDE + cli + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the lightpen pointer. The mouse kernel manages +; a counter for calls to show/hide, and the driver entry point is called only +; if the mouse is currently hidden, and should become visible. For most drivers, +; no special action is required besides enabling the lightpen cursor. +; No return code required. + +SHOW: sei + jsr CSHOW + cli + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the lightpen bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in .XA. +; No checks are done if the lightpen is currently inside the box, that is the job +; of the caller. It is not necessary to validate the parameters; trust the +; caller; and, save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX) - 1 + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + cli + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the lightpen bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in .XA. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX) - 1 +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: X on the stack and Y in .XA. The C wrapper will +; remove the parameter from the stack on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: sei ; No interrupts + jsr MoveY + + ldy #$01 + lda (sp),y + tax + dey + lda (sp),y + jsr MoveX ; Move the cursor + + cli ; Allow interrupts + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in .XA. + +BUTTONS: + ldx #15 ; To system bank + stx IndReg + ldy #CIA::PRB + lda (cia2),y ; Read joystick inputs + ldx ExecReg ; Back to execution bank + stx IndReg + +; Joystick 1, directions in bits 3-0. +; Make the lightpen button look like a 1351 mouse. + + asl a ; Move joystick-left bit ... + asl a ; ... to fire-button bit + eor #MOUSE_BTN_LEFT + and #MOUSE_BTN_LEFT + ldx #>0 + rts + +;---------------------------------------------------------------------------- +; POS: Return the lightpen position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + cli ; Enable interrupts + + iny + sta (ptr1),y ; Store last byte + rts + +;---------------------------------------------------------------------------- +; INFO: Returns lightpen position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here, to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct; so, we'll just +; call _mouse_pos to initiate the struct pointer, and fill the position +; fields. + +INFO: jsr POS + +; Fill in the button state + + jsr BUTTONS ; Will not touch ptr1 + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + rts + +;---------------------------------------------------------------------------- +; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl- +; specific data in ptr1, and the ioctl code in .A. +; Must return an error code in .XA. +; + +IOCTL: lda #MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: Irq.-handler entry point. Called as a subroutine, but in the IRQ context +; (so, be careful). The routine MUST return carry set if the interrupt has been +; 'handled' -- which means that the interrupt source is gone. Otherwise, it +; MUST return carry clear. +; + +IRQ: ldx #15 ; To system bank + stx IndReg + +; Read the VIC-II lightpen registers. + + ldy #VIC_LPEN_Y + lda (vic),y + cmp OldPenY + +; Skip processing if nothing has changed. + + beq @SkipY + sta OldPenY + ldx ExecReg ; Back to execution bank + stx IndReg + +; Subtract the height of the top border, so that the lightpen co-ordinate +; will match the TGI co-ordinate. + + sub #50 + tay ; Remember low byte + ldx #>0 + +; Limit the Y co-ordinate to the bounding box. + + txa + cpy YMin + sbc YMin+1 + bpl @L3 + ldy YMin + ldx YMin+1 + jmp @L4 + +@L3: txa + cpy YMax + sbc YMax+1 + bmi @L4 + ldy YMax + ldx YMax+1 + +@L4: tya + jsr MoveY + + ldx #15 ; To system bank + stx IndReg +@SkipY: ldy #VIC_LPEN_X + lda (vic),y + ldx ExecReg ; Back to execution bank + stx IndReg + cmp OldPenX + +; Skip processing if nothing has changed. + + beq @SkipX + sta OldPenX + +; Adjust the value by the calibration offset. + + sub XOffset + +; Calculate the new X co-ordinate. +; The VIC-II register is eight bits; but, the screen co-ordinate is nine bits. +; Therefore, the VIC-II number is doubled. Then, it points to every other pixel; +; but, it can reach across the screen. + + asl a + tay ; Remember low byte + lda #>0 + rol a + tax ; Remember high byte + +; Limit the X co-ordinate to the bounding box. + + cpy XMin + sbc XMin+1 + bpl @L1 + ldy XMin + ldx XMin+1 + jmp @L2 + +@L1: txa + cpy XMax + sbc XMax+1 + bmi @L2 + ldy XMax + ldx XMax+1 + +@L2: tya + jsr MoveX + +; Done + +@SkipX: clc ; Interrupt not "handled" + rts + +; Move the lightpen pointer to the new Y pos. + +MoveY: sta YPos + stx YPos+1 + jmp CMOVEY + +; Move the lightpen pointer to the new X pos. + +MoveX: sta XPos + stx XPos+1 + jmp CMOVEX diff --git a/libsrc/cbm510/mou/cbm510-joy.s b/libsrc/cbm510/mou/cbm510-joy.s new file mode 100644 index 000000000..9381cf761 --- /dev/null +++ b/libsrc/cbm510/mou/cbm510-joy.s @@ -0,0 +1,445 @@ +; +; Driver for a "joystick mouse". +; +; 2009-09-26, Ullrich von Bassewitz +; 2013-09-05, Greg King +; + + .include "zeropage.inc" + .include "../extzp.inc" + + .include "mouse-kernel.inc" + .include "cbm510.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Header. Includes jump table + +.segment "JUMPTABLE" + +HEADER: + +; Driver signature + + .byte $6d, $6f, $75 ; ASCII "mou" + .byte MOUSE_API_VERSION ; Mouse driver API version number + +; Library reference + + .addr $0000 + +; Jump table + + .addr INSTALL + .addr UNINSTALL + .addr HIDE + .addr SHOW + .addr SETBOX + .addr GETBOX + .addr MOVE + .addr BUTTONS + .addr POS + .addr INFO + .addr IOCTL + .addr IRQ + +; Mouse driver flags + + .byte MOUSE_FLAG_LATE_IRQ + +; Callback table, set by the kernel before INSTALL is called. + +CHIDE: jmp $0000 ; Hide the cursor +CSHOW: jmp $0000 ; Show the cursor +CMOVEX: jmp $0000 ; Move the cursor to x co-ord. +CMOVEY: jmp $0000 ; Move the cursor to y co-ord. + + +;---------------------------------------------------------------------------- +; Constants + +SCREEN_HEIGHT = YSIZE * 8 +SCREEN_WIDTH = XSIZE * 8 + +.scope JOY + UP = %00000001 + DOWN = %00000010 + LEFT = %00000100 + RIGHT = %00001000 + FIRE = %00010000 +.endscope + +;---------------------------------------------------------------------------- +; Global variables. The bounding box values are sorted so that they can be +; written with the least effort in the SETBOX and GETBOX routines; so, don't +; re-order them. + +.bss + +Vars: +YPos: .res 2 ; Current mouse position, y +XPos: .res 2 ; Current mouse position, x +XMin: .res 2 ; X1 value of bounding box +YMin: .res 2 ; Y1 value of bounding box +XMax: .res 2 ; X2 value of bounding box +YMax: .res 2 ; Y2 value of bounding box + +; Temporary value used in the interrupt handler + +Temp: .res 1 + +; Default values for above variables + +.rodata + +.proc DefVars + .word SCREEN_HEIGHT / 2 ; YPos + .word SCREEN_WIDTH / 2 ; XPos + .word 0 ; XMin + .word 0 ; YMin + .word SCREEN_WIDTH - 1 ; XMax + .word SCREEN_HEIGHT - 1 ; YMax +.endproc + +.code + +;---------------------------------------------------------------------------- +; INSTALL routine. Is called after the driver is loaded into memory. If +; possible, check if the hardware is present. +; Must return a MOUSE_ERR_xx code in .XA. + +INSTALL: + +; Initiate variables; just copy the default stuff over. + + ldx #.sizeof(DefVars) - 1 +@L1: lda DefVars,x + sta Vars,x + dex + bpl @L1 + +; Be sure the mouse cursor is invisible and at the default location. We +; need to do that here because our mouse interrupt handler doesn't set the +; mouse position if it hasn't changed. + + sei + jsr CHIDE + lda XPos + ldx XPos+1 + jsr CMOVEX + lda YPos + ldx YPos+1 + jsr CMOVEY + cli + +; Done, return zero. + + ldx #>MOUSE_ERR_OK + txa + rts + +;---------------------------------------------------------------------------- +; UNINSTALL routine. Is called before the driver is removed from memory. +; No return code required (the driver is removed from memory, on return). + +UNINSTALL := HIDE ; Hide cursor, on exit + +;---------------------------------------------------------------------------- +; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide; and, the driver entry point is called only +; if the mouse currently is visible and should get hidden. For most drivers, +; no special action is required besides hiding the mouse cursor. +; No return code required. + +HIDE: sei + jsr CHIDE + cli + rts + +;---------------------------------------------------------------------------- +; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages +; a counter for calls to show/hide; and, the driver entry point is called only +; if the mouse currently is hidden and should become visible. For most drivers, +; no special action is required besides enabling the mouse cursor. +; No return code required. + +SHOW: sei + jsr CSHOW + cli + rts + +;---------------------------------------------------------------------------- +; SETBOX: Set the mouse bounding box. The parameters are passed as they come +; from the C program, that is, a pointer to a mouse_box struct in .XA. +; No checks are done if the mouse currently is inside the box; that is the job +; of the caller. It is not necessary to validate the parameters; trust the +; caller, and save some code here. No return code required. + +SETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX) - 1 + sei + +@L1: lda (ptr1),y + sta XMin,y + dey + bpl @L1 + + cli + rts + +;---------------------------------------------------------------------------- +; GETBOX: Return the mouse bounding box. The parameters are passed as they +; come from the C program, that is, a pointer to a mouse_box struct in .XA. + +GETBOX: sta ptr1 + stx ptr1+1 ; Save data pointer + + ldy #.sizeof (MOUSE_BOX) - 1 + +@L1: lda XMin,y + sta (ptr1),y + dey + bpl @L1 + + rts + +;---------------------------------------------------------------------------- +; MOVE: Move the mouse to a new position. The position is passed as it comes +; from the C program, that is: x on the stack and y in .XA. The C wrapper will +; remove the parameter from the stack, on return. +; No checks are done if the new position is valid (within the bounding box or +; the screen). No return code required. +; + +MOVE: sei ; No interrupts + + jsr MoveY ; Set new y position + + ldy #1 + lda (sp),y + sta XPos+1 + tax + dey + lda (sp),y + jsr MoveX ; Move the pointer + + cli ; Allow interrupts + rts + +;---------------------------------------------------------------------------- +; BUTTONS: Return the button mask in .XA. +; Joystick 2's fire button is the left mouse button. +; Joystick 1's fire button is the right mouse button. + +BUTTONS: + ldx #15 ; Switch to the system bank + stx IndReg + +; Get the fire-button bits + + ldy #CIA::PRA + lda (cia2),y + +; Switch back to the execution bank. + + ldy ExecReg + sty IndReg + +; Joystick 2, fire button is in bit 7. +; Joystick 1, fire button is in bit 6. + + and #%11000000 + asl a ; Move bits 7,6 to bits 1,0 + rol a + rol a + adc #%00001110 ; Move bit 1 to bit 4 + and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT + +; Bits go up when buttons go down. + + eor #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT + ldx #>0 + rts + +;---------------------------------------------------------------------------- +; INFO: Returns mouse position and current button mask in the MOUSE_INFO +; struct pointed to by ptr1. No return code required. +; +; We're cheating here to keep the code smaller: The first fields of the +; mouse_info struct are identical to the mouse_pos struct; so, we just will +; use _mouse_pos to fill the position fields. + +INFO: jsr BUTTONS + +; Fill in the button state. + + ldy #MOUSE_INFO::BUTTONS + sta (ptr1),y + +; jmp POS ; Fall through + +;---------------------------------------------------------------------------- +; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. +; No return code required. + +POS: ldy #MOUSE_POS::XCOORD ; Structure offset + + sei ; Disable interrupts + lda XPos ; Transfer the position + sta (ptr1),y + lda XPos+1 + iny + sta (ptr1),y + lda YPos + iny + sta (ptr1),y + lda YPos+1 + cli ; Enable interrupts + + iny + sta (ptr1),y ; Store last byte + + rts ; Done + +;---------------------------------------------------------------------------- +; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl- +; specific data in ptr1, and the ioctl code in .A. +; Must return an error code in .XA. +; + +IOCTL: lda #MOUSE_ERR_INV_IOCTL + rts + +;---------------------------------------------------------------------------- +; IRQ: Irq.-handler entry point. Called as a subroutine, but in the IRQ context +; (so, be careful). The routine MUST return carry set if the interrupt has been +; 'handled' -- which means that the interrupt source is gone. Otherwise, it +; MUST return carry clear. +; Reads joystick 2. +; + +IRQ: ldy #15 ; Switch to the system bank + sty IndReg + +; Get the direction bits. + + ldy #CIA::PRB + lda (cia2),y ; Read joystick inputs + +; Switch back to the execution bank. + + ldy ExecReg + sty IndReg + +; Joystick 2, directions in bits 7-4. +; Mask the relevant bits. + + and #$F0 + eor #$F0 ; All bits are inverted + sta Temp + +; Check left/right. + + and #(JOY::LEFT | JOY::RIGHT) << 4 + bze @SkipX + +; We will cheat here, and rely on the fact that either the left OR the right +; bit can be active. + + and #JOY::RIGHT << 4 ; Check RIGHT bit + bnz @Right + lda #<-1 + tax + bnz @AddX ; Branch always +@Right: lda #<1 + ldx #>1 + +; Calculate the new x co-ordinate (--> .YA). + +@AddX: add XPos + tay ; Remember low byte + txa + adc XPos+1 + tax + +; Limit the x co-ordinate to the bounding box. + + cpy XMin + sbc XMin+1 + bpl @L1 + ldy XMin + ldx XMin+1 + jmp @L2 + +@L1: txa + cpy XMax + sbc XMax+1 + bmi @L2 + ldy XMax + ldx XMax+1 +@L2: tya + jsr MoveX + +; Calculate the y movement vector. + +@SkipX: lda Temp ; Get joystick again + and #(JOY::UP | JOY::DOWN) << 4 ; Check up/down + bze @SkipY + +; We will cheat here, and rely on the fact that either the up OR the down +; bit can be active. + + and #JOY::UP << 4 ; Check UP bit + bze @Down + lda #<-1 + tax + bnz @AddY +@Down: lda #<1 + ldx #>1 + +; Calculate the new y co-ordinate (--> .YA). + +@AddY: add YPos + tay ; Remember low byte + txa + adc YPos+1 + tax + +; Limit the y co-ordinate to the bounding box. + + cpy YMin + sbc YMin+1 + bpl @L3 + ldy YMin + ldx YMin+1 + jmp @L4 + +@L3: txa + cpy YMax + sbc YMax+1 + bmi @L4 + ldy YMax + ldx YMax+1 +@L4: tya + jsr MoveY + +; Done + +@SkipY: clc ; Interrupt not handled + rts + +; Move the mouse pointer to the new x pos. + +MoveX: sta XPos + stx XPos+1 + jmp CMOVEX + +; Move the mouse pointer to the new y pos. + +MoveY: sta YPos + stx YPos+1 + jmp CMOVEY diff --git a/libsrc/cbm510/mouse_stat_stddrv.s b/libsrc/cbm510/mouse_stat_stddrv.s new file mode 100644 index 000000000..71eec00ee --- /dev/null +++ b/libsrc/cbm510/mouse_stat_stddrv.s @@ -0,0 +1,13 @@ +; +; Address of the static standard mouse driver +; +; 2012-11-01, Oliver Schmidt +; 2013-08-06, Greg King +; +; const void mouse_static_stddrv[]; +; + + .export _mouse_static_stddrv + .import _cbm510_joy_mou + +_mouse_static_stddrv := _cbm510_joy_mou diff --git a/libsrc/cbm510/mouse_stddrv.s b/libsrc/cbm510/mouse_stddrv.s new file mode 100644 index 000000000..7f6ec42a2 --- /dev/null +++ b/libsrc/cbm510/mouse_stddrv.s @@ -0,0 +1,16 @@ +; +; Name of the standard mouse driver +; +; 2009-09-11, Ullrich von Bassewitz +; 2013-06-25, Greg King +; +; const char mouse_stddrv[]; +; + + .export _mouse_stddrv + +.rodata + +_mouse_stddrv: .asciiz "cbm510-joy.mou" + + diff --git a/libsrc/cbm510/mouseref.s b/libsrc/cbm510/mouseref.s new file mode 100644 index 000000000..90aeedf3a --- /dev/null +++ b/libsrc/cbm510/mouseref.s @@ -0,0 +1,23 @@ +; +; Pointer for library references by device drivers. +; +; 2013-07-25, Greg King +; + + .export mouse_libref, _pen_adjuster + + .data + +mouse_libref: ; generic label for mouse-kernel + +; A program optionally can set this pointer to a function that gives +; a calibration value to a driver. If this pointer isn't NULL, +; then a driver that wants a value can call that function. +; +; The function might read a value from a file; or, it might ask the user +; to help calibrate the driver. +; +; void __fastcall__ (*pen_adjuster)(unsigned char *) = NULL; +; +_pen_adjuster: + .addr $0000 diff --git a/libsrc/cbm510/pencalib.c b/libsrc/cbm510/pencalib.c new file mode 100755 index 000000000..3ff3faf4c --- /dev/null +++ b/libsrc/cbm510/pencalib.c @@ -0,0 +1,94 @@ +/* +** Calibrate lightpen drivers to the current video hardware. +** +** 2013-09-05, Greg King +** +*/ + + +#include +#include +#include + + +#define COMMAND1 "Adjust by clicking on line." +#define COMMAND2 "Finish by clicking off bar." + + +/* +** There is a delay between when the VIC sends its signal, and when the display +** shows that signal. There is another delay between the display and when +** the lightpen says that it saw that signal. Each display and pen is different. +** Therefore, the driver must be calibrated to them. A white bar is painted on +** the screen; and, a line is drawn down the middle of it. When the user clicks +** on that line, the difference between its position and where the VIC thinks +** that the pen is pointing becomes an offset that is subtracted from what the +** VIC sees. +*/ +void __fastcall__ pen_calibrate (unsigned char *XOffset) +{ + unsigned char oldBg = bgcolor (COLOR_BLUE); + unsigned char oldText = textcolor (COLOR_GRAY3); + unsigned char oldRev = revers (1); + unsigned char sprite0Color = peekbsys ((unsigned)&VIC.spr_color[0]); + unsigned char width, width2, height, height4, height8; + struct mouse_info info; + + screensize (&width, &height); + width2 = width / 2; + height4 = height / 4; + height8 = height4 * 8; + + /* Draw a bar and line. */ + + clrscr (); + cclearxy (0, height4, height4 * width); + cvlinexy (width2, height4 + 1, height4 - 2); + revers (0); + + /* Print instructions. */ + + cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1); + cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2); + + pokebsys ((unsigned)&VIC.spr_color[0], COLOR_GRAY2); + mouse_show (); + mouse_move (width2 * 8, height8 / 2); + + for (;;) { + /* Wait for the main button to be released. */ + + do ; while ((mouse_buttons () & MOUSE_BTN_LEFT)); + + /* Wait for the main button to be pressed. */ + + do { + mouse_info (&info); + } while (!(info.buttons & MOUSE_BTN_LEFT)); + + /* Find out if the pen is on or off the bar. */ + + if (info.pos.y < height8 || info.pos.y >= height8 * 2) { + break; + } + + /* On the bar; adjust the offset. */ + /* Characters are eight pixels wide. + ** The VIC-II sees every other pixel; + ** so, we use half of the difference. + */ + + *XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2; + } + + /* Off the bar; wait for the main button to be released. */ + + do ; while ((mouse_buttons () & MOUSE_BTN_LEFT)); + + mouse_hide (); + pokebsys ((unsigned)&VIC.spr_color[0], sprite0Color); + revers (oldRev); + textcolor (oldText); + bgcolor (oldBg); + clrscr (); +} diff --git a/libsrc/common/strlower.s b/libsrc/common/strlower.s index 9df79b732..848a4faff 100644 --- a/libsrc/common/strlower.s +++ b/libsrc/common/strlower.s @@ -1,8 +1,9 @@ ; -; Ullrich von Bassewitz, 02.06.1998 +; 1998-06-02, Ullrich von Bassewitz +; 2013-08-28, Greg King ; -; char* strlower (char* s); -; char* strlwr (char* s); +; char* __fastcall__ strlower (char* s); +; char* __fastcall__ strlwr (char* s); ; ; Non-ANSI ; @@ -19,7 +20,7 @@ _strlwr: sta ptr1 ; Save s (working copy) stx ptr1+1 sta ptr2 - sta ptr2+1 ; save function result + stx ptr2+1 ; save function result ldy #0 loop: lda (ptr1),y ; get character diff --git a/libsrc/common/strtol.c b/libsrc/common/strtol.c index b7ccdf24c..f3ce08a35 100644 --- a/libsrc/common/strtol.c +++ b/libsrc/common/strtol.c @@ -102,7 +102,7 @@ long __fastcall__ strtol (const char* nptr, char** endptr, int base) */ if (endptr) { if (CvtCount > 0) { - *endptr = (char*) S - 1; + *endptr = (char*) S; } else { *endptr = (char*) nptr; } diff --git a/libsrc/common/strtoul.c b/libsrc/common/strtoul.c index fa0d64f42..54466db36 100644 --- a/libsrc/common/strtoul.c +++ b/libsrc/common/strtoul.c @@ -97,7 +97,7 @@ unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base) */ if (endptr) { if (CvtCount > 0) { - *endptr = (char*) S - 1; + *endptr = (char*) S; } else { *endptr = (char*) nptr; } diff --git a/libsrc/common/strupper.s b/libsrc/common/strupper.s index d7aa2f914..bf0d3b622 100644 --- a/libsrc/common/strupper.s +++ b/libsrc/common/strupper.s @@ -1,8 +1,9 @@ ; -; Ullrich von Bassewitz, 02.06.1998 +; 1998-06-02, Ullrich von Bassewitz +; 2013-08-28, Greg King ; -; char* strupper (char* s); -; char* strupr (char* s); +; char* __fastcall__ strupper (char* s); +; char* __fastcall__ strupr (char* s); ; ; Non-ANSI ; @@ -19,7 +20,7 @@ _strupr: sta ptr1 ; Save s (working copy) stx ptr1+1 sta ptr2 - sta ptr2+1 ; save function result + stx ptr2+1 ; save function result ldy #0 loop: lda (ptr1),y ; get character diff --git a/libsrc/common/time.s b/libsrc/common/time.s index 2157eb49f..140d47e2c 100644 --- a/libsrc/common/time.s +++ b/libsrc/common/time.s @@ -27,10 +27,10 @@ ; Restore timep and check if it is NULL pla - sta ptr1 + sta ptr1+1 pla - sta ptr1+1 ; Restore timep - ora ptr1 ; timep == 0? + sta ptr1 ; Restore timep + ora ptr1+1 ; timep == 0? beq @L1 ; timep is not NULL, store the result there diff --git a/libsrc/pet/mainargs.s b/libsrc/pet/mainargs.s index 9a63f50c2..0d5b18987 100644 --- a/libsrc/pet/mainargs.s +++ b/libsrc/pet/mainargs.s @@ -13,7 +13,6 @@ MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code NAME_LEN = 16 ; maximum length of command-name -BASIC_BUF= $200 ;--------------------------------------------------------------------------- diff --git a/samples/mousetest.c b/samples/mousetest.c index dd90e0990..7d9409659 100644 --- a/samples/mousetest.c +++ b/samples/mousetest.c @@ -3,7 +3,7 @@ ** Will work for the C64/C128/CBM510/Atari/Apple2. ** ** 2001-09-13, Ullrich von Bassewitz -** 2013-07-25, Greg King +** 2013-09-05, Greg King ** */ @@ -85,7 +85,12 @@ static const unsigned char MouseSprite[64] = { static void __fastcall__ CheckError (const char* S, unsigned char Error) { if (Error != MOUSE_ERR_OK) { - cprintf ("%s: %s(%u)\r\n", S, mouse_geterrormsg (Error), Error); + cprintf ("\n%s: %s(%u)\r\n", S, mouse_geterrormsg (Error), Error); + + /* Wait for a key-press, so that some platforms can show the error + ** message before they remove the current screen. + */ + cgetc(); exit (EXIT_FAILURE); } } @@ -154,7 +159,7 @@ int main (void) cursor (0); clrscr (); - /* The pointer is created before the driver is installed, + /* The pointer should be created before the driver is installed, ** in case a lightpen driver needs it during calibration. */ @@ -178,7 +183,7 @@ int main (void) ** the value will be put into this file, for the next time. ** (Other drivers will ignore this.) */ -#ifdef __CBM__ +#if defined(__C64__) || defined(__C128__) || defined(__CBM510__) pen_adjust ("pen.dat"); #endif @@ -222,8 +227,13 @@ top: /* Put a cross at the center of the screen. */ gotoxy (width / 2 - 3, height / 2 - 1); +#if defined(__CBM__) cprintf ("%3u,%3u\r\n%*s\xDB", width / 2 * 8 + 4, height / 2 * 8 + 4, width / 2, ""); +#else + cprintf ("%3u,%3u\r\n%*s+", width / 2 * 8 + 4, height / 2 * 8 + 4, + width / 2, ""); +#endif /* Test loop */ ShowState (Jailed, Invisible); diff --git a/src/ar65/library.c b/src/ar65/library.c index 9fdbf9e91..9046e315f 100644 --- a/src/ar65/library.c +++ b/src/ar65/library.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2012, Ullrich von Bassewitz */ +/* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -38,6 +38,7 @@ #include /* common */ +#include "cmdline.h" #include "exprdefs.h" #include "libdefs.h" #include "print.h" @@ -60,7 +61,7 @@ /*****************************************************************************/ - + /* Name of the library file */ const char* LibName = 0; @@ -101,7 +102,7 @@ static void ReadHeader (void) } Header.Flags = Read16 (Lib); Header.IndexOffs = Read32 (Lib); -} +} @@ -229,7 +230,9 @@ void LibOpen (const char* Name, int MustExist, int NeedTemp) if (MustExist) { Error ("Library `%s' does not exist", Name); } else { - Warning ("Library `%s' not found - will be created", Name); + /* Announce the library's creation if ar65 is verbose. */ + Print (stdout, 1, + "%s: Library `%s' will be created.\n", ProgName, Name); } } else { @@ -307,7 +310,7 @@ static void LibCheckExports (ObjData* O) unsigned I; /* Let the user know what we do */ - Print (stdout, 1, "Module `%s' (%u exports):\n", O->Name, CollCount (&O->Exports)); + Print (stdout, 2, "Module `%s' (%u exports):\n", O->Name, CollCount (&O->Exports)); /* Insert the exports into the global table */ for (I = 0; I < CollCount (&O->Exports); ++I) { @@ -316,7 +319,7 @@ static void LibCheckExports (ObjData* O) const char* Name = CollConstAt (&O->Exports, I); /* Insert the name into the hash table */ - Print (stdout, 1, " %s\n", Name); + Print (stdout, 2, " %s\n", Name); ExpInsert (Name, O); } } diff --git a/src/ar65/main.c b/src/ar65/main.c index cf3c428f5..9af480632 100644 --- a/src/ar65/main.c +++ b/src/ar65/main.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2012, Ullrich von Bassewitz */ +/* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -60,11 +60,12 @@ static void Usage (void) /* Print usage information and exit */ { - printf ("Usage: %s lib file|module ...\n" - "Operation is one of:\n" + fprintf (stderr, "Usage: %s lib file|module ...\n" + "Operations are some of:\n" "\ta\tAdd modules\n" "\td\tDelete modules\n" "\tl\tList library contents\n" + "\tv\tIncrease verbosity (put before other operation)\n" "\tx\tExtract modules\n" "\tV\tPrint the archiver version\n", ProgName); diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 4d3fe76e6..dfa14d3f8 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2001-2009 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2001-2013, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -58,7 +58,8 @@ typedef enum { LI_DIRECT = 0x01, /* Direct op may be used */ LI_RELOAD_Y = 0x02, /* Reload index register Y */ LI_REMOVE = 0x04, /* Load may be removed */ - LI_DUP_LOAD = 0x08, /* Duplicate load */ + LI_DONT_REMOVE = 0x08, /* Load may not be removed */ + LI_DUP_LOAD = 0x10, /* Duplicate load */ } LI_FLAGS; /* Structure that tells us how to load the lhs values */ @@ -245,6 +246,18 @@ static void AdjustLoadInfo (LoadInfo* LI, int Index, int Change) +static void HonourUseAndChg (LoadRegInfo* RI, unsigned Reg, const CodeEntry* E) +/* Honour use and change flags for an instruction */ +{ + if (E->Chg & Reg) { + ClearLoadRegInfo (RI); + } else if ((E->Use & Reg) && RI->LoadIndex >= 0) { + RI->Flags |= LI_DONT_REMOVE; + } +} + + + static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) /* Track loads for a code entry */ { @@ -349,15 +362,9 @@ static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) ClearLoadRegInfo (&LI->Y); } else { - if (E->Chg & REG_A) { - ClearLoadRegInfo (&LI->A); - } - if (E->Chg & REG_X) { - ClearLoadRegInfo (&LI->X); - } - if (E->Chg & REG_Y) { - ClearLoadRegInfo (&LI->Y); - } + HonourUseAndChg (&LI->A, REG_A, E); + HonourUseAndChg (&LI->X, REG_X, E); + HonourUseAndChg (&LI->Y, REG_Y, E); } } @@ -646,7 +653,7 @@ static void RemoveRegLoads (StackOpData* D, LoadInfo* LI) /* Both registers may be loaded with one insn, but DelEntry will in this * case clear the other one. */ - if (LI->A.Flags & LI_REMOVE) { + if ((LI->A.Flags & (LI_REMOVE | LI_DONT_REMOVE)) == LI_REMOVE) { if (LI->A.LoadIndex >= 0) { DelEntry (D, LI->A.LoadIndex); } @@ -654,7 +661,7 @@ static void RemoveRegLoads (StackOpData* D, LoadInfo* LI) DelEntry (D, LI->A.XferIndex); } } - if (LI->X.Flags & LI_REMOVE) { + if ((LI->X.Flags & (LI_REMOVE | LI_DONT_REMOVE)) == LI_REMOVE) { if (LI->X.LoadIndex >= 0) { DelEntry (D, LI->X.LoadIndex); } @@ -875,7 +882,7 @@ static unsigned Opt_tosshift (StackOpData* D, const char* Name) AddStoreA (D); /* Be sure to setup IP after adding the stores, otherwise it will get - * messed up. + * messed up. */ D->IP = D->OpIndex+1; diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 558967aa2..2125eb430 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1952,6 +1952,7 @@ static void hie_internal (const GenDesc* Ops, /* List of generators */ type = CF_CONST; if ((Gen->Flags & GEN_NOPUSH) == 0) { g_push (ltype, 0); + } else { ltype |= CF_REG; /* Value is in register */ } diff --git a/src/ld65/main.c b/src/ld65/main.c index 25a6c76f8..84af34d54 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -114,7 +114,6 @@ static void Usage (void) " --config name\t\tUse linker config file\n" " --dbgfile name\tGenerate debug information\n" " --define sym=val\tDefine a symbol\n" - " --dump-config name\tDump a builtin configuration\n" " --end-group\t\tEnd a library group\n" " --force-import sym\tForce an import of symbol `sym'\n" " --help\t\tHelp (this text)\n" diff --git a/testcode/lib/arg-test.c b/testcode/lib/arg-test.c index c752acaeb..5c28faec0 100644 --- a/testcode/lib/arg-test.c +++ b/testcode/lib/arg-test.c @@ -9,6 +9,9 @@ int main (int argc, char* argv[]) for (I = 0; I < argc; ++I) { printf ("argv[%2d]: \"%s\"\n", I, argv[I]); } + + printf ("\n"); + getchar (); return EXIT_SUCCESS; } diff --git a/testcode/lib/atari/ostype.c b/testcode/lib/atari/ostype.c index e97bd00e6..f5e9296ca 100644 --- a/testcode/lib/atari/ostype.c +++ b/testcode/lib/atari/ostype.c @@ -40,6 +40,7 @@ int main(void) printf("is'a a XL/XE, %s, Rev. %d\n",palntsc ? "PAL" : "NTSC",minor); break; } - printf("hit to continure...\n"); + printf("hit to continue...\n"); c = getchar(); + return 0; } diff --git a/testcode/lib/atari/sys.c b/testcode/lib/atari/sys.c new file mode 100644 index 000000000..a35be9dac --- /dev/null +++ b/testcode/lib/atari/sys.c @@ -0,0 +1,37 @@ +/* + * testprogram for _sys() function on Atari + * + * 17-Sep-2013, chris@groessler.org + * + * uses PUTCHR IOCB function to display a string + */ + +#include +#include <6502.h> +#include + +static struct regs regs; +static struct __iocb *iocb = &IOCB; /* use IOCB #0 */ + +static char message[] = "I'm the sys test text\n"; + +int main(void) +{ + /* setup IOCB for CIO call */ + iocb->buffer = message; + iocb->buflen = sizeof(message) - 1; + iocb->command = IOCB_PUTCHR; + + /* setup input registers */ + regs.x = 0; /* IOCB #0 */ + regs.pc = 0xe456; /* CIOV */ + + /* call CIO */ + _sys(®s); + + if (regs.y != 1) + cprintf("CIO error 0x%02\r\n", regs.y); + + cgetc(); + return 0; +} diff --git a/testcode/lib/em-test.c b/testcode/lib/em-test.c index c7fee6a59..41a7eb2c8 100644 --- a/testcode/lib/em-test.c +++ b/testcode/lib/em-test.c @@ -20,6 +20,10 @@ #define DRIVERNAME "a2e.auxmem.emd" #elif defined(__APPLE2__) #define DRIVERNAME "a2.auxmem.emd" +#elif defined(__ATARIXL__) +#define DRIVERNAME "atrx130.emd" +#elif defined(__ATARI__) +#define DRIVERNAME "atr130.emd" #else #define DRIVERNAME "unknown" #error "Unknown target system" @@ -63,6 +67,9 @@ static void cmp (unsigned page, register const unsigned* buf, cprintf ("\r\nData mismatch in page $%04X at $%04X\r\n" "Data is $%04X (should be $%04X)\r\n", page, buf, *buf, num); +#ifdef __ATARI__ + cgetc (); +#endif exit (EXIT_FAILURE); } } @@ -84,6 +91,9 @@ int main (void) if (Res != EM_ERR_OK) { cprintf ("Error in em_load_driver: %u\r\n", Res); cprintf ("os: %u, %s\r\n", _oserror, _stroserror (_oserror)); +#ifdef __ATARI__ + cgetc (); +#endif exit (EXIT_FAILURE); } atexit (cleanup); @@ -195,6 +205,10 @@ int main (void) /* Success */ cprintf ("\r\nPassed!\r\n"); +#ifdef __ATARI__ + cgetc (); +#endif + return 0; } diff --git a/testcode/lib/exec-test1.c b/testcode/lib/exec-test1.c new file mode 100644 index 000000000..e2548fb0a --- /dev/null +++ b/testcode/lib/exec-test1.c @@ -0,0 +1,24 @@ +/* +** These programs test CC65's exec() program-chaining function. +** exec-test1 runs exec-test2 -- that tests the loading and starting of another +** program. Then, exec-test2 runs arg-test -- that tests command-line argument +** passing. +** +** 2013-08-24, Greg King +*/ + +#include +#include +#include +#include + +int main (void) { + clrscr (); + cprintf ("\nExec-test #1 -- launching #2...\r\n"); + + exec ("exec-test2", ""); + + cprintf ("\nFailed to find #2:\r\n %s.\r\n", _stroserror (_oserror)); + cgetc (); + return _oserror; +} diff --git a/testcode/lib/exec-test2.c b/testcode/lib/exec-test2.c new file mode 100644 index 000000000..e6c844a8e --- /dev/null +++ b/testcode/lib/exec-test2.c @@ -0,0 +1,23 @@ +/* +** These programs test CC65's exec() program-chaining function. +** exec-test1 runs exec-test2 -- that tests the loading and starting of another +** program. Then, exec-test2 runs arg-test -- that tests command-line argument +** passing. +** +** 2013-08-24, Greg King +*/ + +#include +#include +#include +#include + +int main (void) { + cprintf ("\nExec-test #2 -- launching arg-test...\r\n\n"); + + exec ("arg-test", "arg1 arg2 \"\" arg4"); + + cprintf ("\nFailed to find arg-test:\r\n %s.\r\n", _stroserror (_oserror)); + cgetc (); + return _oserror; +} diff --git a/testcode/lib/tinyshell.c b/testcode/lib/tinyshell.c index f4a18126b..141065257 100644 --- a/testcode/lib/tinyshell.c +++ b/testcode/lib/tinyshell.c @@ -5,12 +5,22 @@ #define VERSION_ASC "0.90" -#define KEYB_BUFSZ 80 -#define PROMPT ">>> " #ifdef __ATARI__ #define UPPERCASE /* define (e.g. for Atari) to convert filenames etc. to upper case */ +#define HAVE_SUBDIRS #endif +#ifdef __APPLE2__ +#define HAVE_SUBDIRS +#endif + +#ifdef __CC65__ +#define CHECK_SP +#endif + +#define KEYB_BUFSZ 80 +#define PROMPT ">>> " + #include #include #include @@ -19,6 +29,7 @@ #ifndef __CC65__ #include #include +#define HAVE_SUBDIRS #else #define MAXPATHLEN 64 #endif @@ -26,6 +37,10 @@ #include #include +#ifdef CHECK_SP +extern unsigned int getsp(void); /* comes from getsp.s */ +#endif + #define CMD_NOTHING 0 #define CMD_INVALID 1 #define CMD_HELP 2 @@ -38,7 +53,10 @@ #define CMD_RENAME 9 #define CMD_COPY 10 #define CMD_PWD 11 +#define CMD_CLS 12 +#define CMD_VERBOSE 13 +static unsigned char verbose; static unsigned char terminate; static unsigned char cmd; static unsigned char *cmd_asc, *arg1, *arg2, *arg3; @@ -56,11 +74,13 @@ struct cmd_table { { "ls", CMD_LS }, { "dir", CMD_LS }, { "md", CMD_MKDIR }, +#ifdef HAVE_SUBDIRS { "mkdir", CMD_MKDIR }, { "rd", CMD_RMDIR }, { "rmdir", CMD_RMDIR }, { "cd", CMD_CHDIR }, { "chdir", CMD_CHDIR }, +#endif { "rm", CMD_RM }, { "del", CMD_RM }, { "cp", CMD_COPY }, @@ -68,6 +88,10 @@ struct cmd_table { { "mv", CMD_RENAME }, { "ren", CMD_RENAME }, { "pwd", CMD_PWD }, +#ifdef __ATARI__ + { "cls", CMD_CLS }, +#endif + { "verbose", CMD_VERBOSE }, { NULL, 0 } }; @@ -82,6 +106,22 @@ static void get_command(void) { unsigned char i = 0; +#ifdef CHECK_SP + static char firstcall = 1; + static unsigned int good_sp; + unsigned int sp; + if (firstcall) + sp = good_sp = getsp(); + else + sp = getsp(); + + if (sp != good_sp) { + printf("SP: 0x%04X ***MISMATCH*** 0x%04X\n", sp, good_sp); + } + else if (verbose) + printf("SP: 0x%04X\n", sp); +#endif + arg1 = arg2 = arg3 = NULL; /* issue prompt */ @@ -132,6 +172,10 @@ static void cmd_help(void) puts("cd, chdir - change directory or drive"); puts("md, mkdir - make directory or drive"); puts("rd, rmdir - remove directory or drive"); +#ifdef __ATARI__ + puts("cls - clear screen"); +#endif + puts("verbose - set verbosity level"); puts("sorry, you cannot start programs here"); } @@ -173,6 +217,8 @@ static void cmd_ls(void) else arg = "."; + if (verbose) + printf("Buffer addr: %p\n", arg); dir = opendir(arg); #ifdef __ATARI__ if (need_free) free(arg); @@ -203,6 +249,8 @@ static void cmd_rm(void) printf("remove failed: %s\n", strerror(errno)); } +#ifdef HAVE_SUBDIRS + static void cmd_mkdir(void) { if (!arg1 || arg2) { @@ -262,6 +310,8 @@ static void cmd_pwd(void) printf("malloc %u bytes failed: %s\n", MAXPATHLEN, strerror(errno)); return; } + if (verbose) + printf("Buffer addr: %p\n", buf); if (!getcwd(buf, MAXPATHLEN)) { printf("getcwd failed: %s\n", strerror(errno)); free(buf); @@ -272,6 +322,8 @@ static void cmd_pwd(void) free(buf); } +#endif /* #ifdef HAVE_SUBDIRS */ + static void cmd_rename(void) { if (!arg2 || arg3) { @@ -309,6 +361,8 @@ static void cmd_copy(void) printf("malloc %u bytes failed: %s\n", cpbuf_sz, strerror(errno)); return; } + if (verbose) + printf("Buffer addr: %p\n", buf); while (1) { if (srcfd == -1) { @@ -349,6 +403,33 @@ static void cmd_copy(void) if (dstfd >= 0) close(dstfd); } +#ifdef __ATARI__ +static void cmd_cls(void) +{ + printf("\f"); +} +#endif + +static void cmd_verbose(void) +{ + unsigned long verb; + char *endptr; + + if (!arg1 || arg2) { + puts("usage: verbose "); + return; + } + + verb = strtoul(arg1, &endptr, 10); + if (verb > 255 || *endptr) { + puts("invalid verbosity level"); + return; + } + + verbose = verb; + printf("verbosity level set to %d\n", verbose); +} + static void run_command(void) { switch (cmd) { @@ -359,12 +440,18 @@ static void run_command(void) case CMD_QUIT: terminate = 1; return; case CMD_LS: cmd_ls(); return; case CMD_RM: cmd_rm(); return; +#ifdef HAVE_SUBDIRS case CMD_CHDIR: cmd_chdir(); return; case CMD_MKDIR: cmd_mkdir(); return; case CMD_RMDIR: cmd_rmdir(); return; case CMD_PWD: cmd_pwd(); return; +#endif case CMD_RENAME: cmd_rename(); return; case CMD_COPY: cmd_copy(); return; +#ifdef __ATARI__ + case CMD_CLS: cmd_cls(); return; +#endif + case CMD_VERBOSE: cmd_verbose(); return; } }