1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-23 19:29:37 +00:00

Merge branch 'master' into master

This commit is contained in:
jedeoric 2021-03-01 23:03:34 +01:00 committed by GitHub
commit ba4310f589
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
143 changed files with 3214 additions and 1314 deletions

View File

@ -15,6 +15,7 @@ PROMPT := $33 ; Used by GETLN
RNDL := $4E ; Random counter low
RNDH := $4F ; Random counter high
HIMEM := $73 ; Highest available memory address+1
CURLIN := $75 ; Current line number being executed
;-----------------------------------------------------------------------------
; Vectors

View File

@ -7,6 +7,7 @@
; Zero page, Commodore stuff
TXTPTR := $3D ; Pointer into BASIC source code
STATUS := $90 ; Kernal I/O completion status
TIME := $A0 ; 60HZ clock
FNAM_LEN := $B7 ; Length of filename
SECADR := $B9 ; Secondary address

View File

@ -9,6 +9,7 @@
VARTAB := $2D ; Pointer to start of BASIC variables
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
TXTPTR := $7A ; Pointer into BASIC source code
STATUS := $90 ; Kernal I/O completion status
TIME := $A0 ; 60 HZ clock
FNAM_LEN := $B7 ; Length of filename
SECADR := $B9 ; Secondary address

View File

@ -2,18 +2,20 @@
CPU_ISET_NONE = $0001
CPU_ISET_6502 = $0002
CPU_ISET_6502X = $0004
CPU_ISET_65SC02 = $0008
CPU_ISET_65C02 = $0010
CPU_ISET_65816 = $0020
CPU_ISET_SWEET16 = $0040
CPU_ISET_HUC6280 = $0080
;CPU_ISET_M740 = $0100 not actually implemented
CPU_ISET_4510 = $0200
CPU_ISET_6502DTV = $0008
CPU_ISET_65SC02 = $0010
CPU_ISET_65C02 = $0020
CPU_ISET_65816 = $0040
CPU_ISET_SWEET16 = $0080
CPU_ISET_HUC6280 = $0100
;CPU_ISET_M740 = $0200 not actually implemented
CPU_ISET_4510 = $0400
; CPU capabilities
CPU_NONE = CPU_ISET_NONE
CPU_6502 = CPU_ISET_6502
CPU_6502X = CPU_ISET_6502|CPU_ISET_6502X
CPU_6502DTV = CPU_ISET_6502|CPU_ISET_6502X|CPU_ISET_6502DTV
CPU_65SC02 = CPU_ISET_6502|CPU_ISET_65SC02
CPU_65C02 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02
CPU_65816 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65816

View File

@ -505,4 +505,12 @@ OPC_ISC_aby = $FB
OPC_NOP_abx = $FC
OPC_ISC_abx = $FF
.if (.cpu .bitand ::CPU_ISET_6502DTV)
OPC_BRA = $12
OPC_SAC_imm = $32
OPC_SIR_imm = $42
.endif
.endif

View File

@ -10,6 +10,7 @@ TMPPTR := $22 ; Temporary ptr used by BASIC
VARTAB := $2D ; Pointer to start of BASIC variables
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
TXTPTR := $3B ; Pointer into BASIC source code
STATUS := $90 ; Kernal I/O completion status
TIME := $A3 ; 60HZ clock
FNAM_LEN := $AB ; Length of filename
LFN := $AC ; Logical file number

View File

@ -9,6 +9,7 @@
VARTAB := $2D ; Pointer to start of BASIC variables
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
TXTPTR := $7A ; Pointer into BASIC source code
STATUS := $90 ; Kernal I/O completion status
TIME := $A0 ; 60HZ clock
FNAM_LEN := $B7 ; Length of filename
SECADR := $B9 ; Secondary address

View File

@ -23,7 +23,7 @@ SEGMENTS {
EXEHDR: load = HEADER, type = ro, optional = yes;
STARTUP: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
HGR: load = MAIN, type = rw, optional = yes, start = $2000;
HGR: load = MAIN, type = rw, start = $2000;
CODE: load = MAIN, type = ro start = $4000;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;

View File

@ -23,7 +23,7 @@ SEGMENTS {
EXEHDR: load = HEADER, type = ro, optional = yes;
STARTUP: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
HGR: load = MAIN, type = rw, optional = yes, start = $2000;
HGR: load = MAIN, type = rw, start = $2000;
CODE: load = MAIN, type = ro start = $4000;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;

View File

@ -11,6 +11,7 @@ SYMBOLS {
__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
__CHARGENSIZE__: type = weak, value = $0400;
__STARTADDRESS__: type = export, value = %S;
}
MEMORY {
@ -37,10 +38,10 @@ MEMORY {
TRAILER: file = %O, start = $0000, size = $0006;
# address of relocated character generator
CHARGEN: file = "", define = yes, start = $D800, size = $0400;
CHARGEN: file = "", define = yes, start = $D800, size = __CHARGENSIZE__;
# memory beneath the ROM
HIDDEN_RAM: file = "", define = yes, start = $DC00, size = $FFFA - $DC00;
HIDDEN_RAM: file = "", define = yes, start = $D800 + __CHARGENSIZE__, size = $FFFA - $D800 - __CHARGENSIZE__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
@ -53,7 +54,7 @@ SEGMENTS {
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
LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and MAIN, 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;

View File

@ -6,6 +6,7 @@ SYMBOLS {
__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
__CHARGENSIZE__: type = weak, value = $0400;
__OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay
__STARTADDRESS__: type = export, value = %S;
}
@ -37,10 +38,10 @@ MEMORY {
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;
CHARGEN: file = "", define = yes, start = $E000, size = __CHARGENSIZE__;
# memory beneath the ROM
HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400;
HIDDEN_RAM: file = "", define = yes, start = $E000 + __CHARGENSIZE__, size = $FFFA - $E000 - __CHARGENSIZE__;
# overlays
OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
@ -64,7 +65,7 @@ SEGMENTS {
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
LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and MAIN, 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;

View File

@ -7,6 +7,7 @@ SYMBOLS {
__SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTADDRESS__: type = export, value = %S;
__CHARGENSIZE__: type = weak, value = $0400;
__SYSCHKHDR__: type = export, value = 0; # Disable system check header
__SYSCHKTRL__: type = export, value = 0; # Disable system check trailer
}
@ -26,10 +27,10 @@ MEMORY {
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;
CHARGEN: file = "", define = yes, start = $E000, size = __CHARGENSIZE__;
# memory beneath the ROM
HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400;
HIDDEN_RAM: file = "", define = yes, start = $E000 + __CHARGENSIZE__, size = $FFFA - $E000 - __CHARGENSIZE__;
# UNUSED - hide
UNUSED: file = "", start = $0, size = $10;
@ -47,7 +48,7 @@ SEGMENTS {
EXTZP: load = ZP, type = zp, optional = yes;
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized
LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and MAIN, 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;

View File

@ -6,6 +6,7 @@ SYMBOLS {
__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
__CHARGENSIZE__: type = weak, value = $0400;
__STARTADDRESS__: type = export, value = %S;
}
MEMORY {
@ -35,10 +36,10 @@ MEMORY {
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;
CHARGEN: file = "", define = yes, start = $E000, size = __CHARGENSIZE__;
# memory beneath the ROM
HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400;
HIDDEN_RAM: file = "", define = yes, start = $E000 + __CHARGENSIZE__, size = $FFFA - $E000 - __CHARGENSIZE__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
@ -51,7 +52,7 @@ SEGMENTS {
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
LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and MAIN, 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;

View File

@ -22,8 +22,10 @@ SEGMENTS {
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
ONCE: load = MAIN, type = ro, optional = yes;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
INIT: load = MAIN, type = bss, optional = yes;
BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {

View File

@ -16,8 +16,6 @@ MEMORY {
HEADER: file = %O, define = yes, start = %S, size = $000D;
MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __HEADER_LAST__;
BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __ONCE_RUN__ - __STACKSIZE__;
# BRAM00ADDR: file = "%O.00", start = __BANKRAMSTART__ - 2, size = $0002;
# BRAM00: file = "%O.00", start = __BANKRAMSTART__, size = __BANKRAMSIZE__;
BRAM01ADDR: file = "%O.01", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM01: file = "%O.01", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $01;
BRAM02ADDR: file = "%O.02", start = __BANKRAMSTART__ - 2, size = $0002;
@ -36,64 +34,62 @@ MEMORY {
BRAM08: file = "%O.08", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $08;
BRAM09ADDR: file = "%O.09", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM09: file = "%O.09", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $09;
BRAM0AADDR: file = "%O.0a", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0A: file = "%O.0a", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0A;
BRAM0BADDR: file = "%O.0b", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0B: file = "%O.0b", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0B;
BRAM0CADDR: file = "%O.0c", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0C: file = "%O.0c", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0C;
BRAM0DADDR: file = "%O.0d", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0D: file = "%O.0d", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0D;
BRAM0EADDR: file = "%O.0e", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0E: file = "%O.0e", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0E;
BRAM0FADDR: file = "%O.0f", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0F: file = "%O.0f", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0F;
BRAM0AADDR: file = "%O.0A", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0A: file = "%O.0A", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0A;
BRAM0BADDR: file = "%O.0B", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0B: file = "%O.0B", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0B;
BRAM0CADDR: file = "%O.0C", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0C: file = "%O.0C", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0C;
BRAM0DADDR: file = "%O.0D", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0D: file = "%O.0D", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0D;
BRAM0EADDR: file = "%O.0E", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0E: file = "%O.0E", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0E;
BRAM0FADDR: file = "%O.0F", start = __BANKRAMSTART__ - 2, size = $0002;
BRAM0F: file = "%O.0F", start = __BANKRAMSTART__, size = __BANKRAMSIZE__, bank = $0F;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
STARTUP: load = MAIN, type = ro;
STARTUP: load = MAIN, type = ro, optional = yes;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
INIT: load = MAIN, type = rw;
INIT: load = MAIN, type = rw, optional = yes;
ONCE: load = MAIN, type = ro, define = yes;
BSS: load = BSS, type = bss, define = yes;
# BRAM00ADDR: load = BRAM00ADDR, type = ro, optional = yes;
# BANKRAM00: load = BRAM00, type = rw, define = yes, optional = yes;
BRAM01ADDR: load = BRAM01ADDR, type = ro, optional = yes;
BANKRAM01: load = BRAM01, type = rw, define = yes, optional = yes;
BANKRAM01: load = BRAM01, type = rw, optional = yes, define = yes;
BRAM02ADDR: load = BRAM02ADDR, type = ro, optional = yes;
BANKRAM02: load = BRAM02, type = rw, define = yes, optional = yes;
BANKRAM02: load = BRAM02, type = rw, optional = yes, define = yes;
BRAM03ADDR: load = BRAM03ADDR, type = ro, optional = yes;
BANKRAM03: load = BRAM03, type = rw, define = yes, optional = yes;
BANKRAM03: load = BRAM03, type = rw, optional = yes, define = yes;
BRAM04ADDR: load = BRAM04ADDR, type = ro, optional = yes;
BANKRAM04: load = BRAM04, type = rw, define = yes, optional = yes;
BANKRAM04: load = BRAM04, type = rw, optional = yes, define = yes;
BRAM05ADDR: load = BRAM05ADDR, type = ro, optional = yes;
BANKRAM05: load = BRAM05, type = rw, define = yes, optional = yes;
BANKRAM05: load = BRAM05, type = rw, optional = yes, define = yes;
BRAM06ADDR: load = BRAM06ADDR, type = ro, optional = yes;
BANKRAM06: load = BRAM06, type = rw, define = yes, optional = yes;
BANKRAM06: load = BRAM06, type = rw, optional = yes, define = yes;
BRAM07ADDR: load = BRAM07ADDR, type = ro, optional = yes;
BANKRAM07: load = BRAM07, type = rw, define = yes, optional = yes;
BANKRAM07: load = BRAM07, type = rw, optional = yes, define = yes;
BRAM08ADDR: load = BRAM08ADDR, type = ro, optional = yes;
BANKRAM08: load = BRAM08, type = rw, define = yes, optional = yes;
BANKRAM08: load = BRAM08, type = rw, optional = yes, define = yes;
BRAM09ADDR: load = BRAM09ADDR, type = ro, optional = yes;
BANKRAM09: load = BRAM09, type = rw, define = yes, optional = yes;
BANKRAM09: load = BRAM09, type = rw, optional = yes, define = yes;
BRAM0AADDR: load = BRAM0AADDR, type = ro, optional = yes;
BANKRAM0A: load = BRAM0A, type = rw, define = yes, optional = yes;
BANKRAM0A: load = BRAM0A, type = rw, optional = yes, define = yes;
BRAM0BADDR: load = BRAM0BADDR, type = ro, optional = yes;
BANKRAM0B: load = BRAM0B, type = rw, define = yes, optional = yes;
BANKRAM0B: load = BRAM0B, type = rw, optional = yes, define = yes;
BRAM0CADDR: load = BRAM0CADDR, type = ro, optional = yes;
BANKRAM0C: load = BRAM0C, type = rw, define = yes, optional = yes;
BANKRAM0C: load = BRAM0C, type = rw, optional = yes, define = yes;
BRAM0DADDR: load = BRAM0DADDR, type = ro, optional = yes;
BANKRAM0D: load = BRAM0D, type = rw, define = yes, optional = yes;
BANKRAM0D: load = BRAM0D, type = rw, optional = yes, define = yes;
BRAM0EADDR: load = BRAM0EADDR, type = ro, optional = yes;
BANKRAM0E: load = BRAM0E, type = rw, define = yes, optional = yes;
BANKRAM0E: load = BRAM0E, type = rw, optional = yes, define = yes;
BRAM0FADDR: load = BRAM0FADDR, type = ro, optional = yes;
BANKRAM0F: load = BRAM0F, type = rw, define = yes, optional = yes;
BANKRAM0F: load = BRAM0F, type = rw, optional = yes, define = yes;
}
FEATURES {
CONDES: type = constructor,

View File

@ -19,12 +19,12 @@ SEGMENTS {
EXTZP: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
STARTUP: load = MAIN, type = ro;
STARTUP: load = MAIN, type = ro, optional = yes;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
INIT: load = MAIN, type = rw;
INIT: load = MAIN, type = rw, optional = yes;
ONCE: load = MAIN, type = ro, define = yes;
BSS: load = BSS, type = bss, define = yes;
}

View File

@ -1,4 +1,4 @@
# supervision 1284kbyte cartridge with bankswitching
# supervision 128kbyte cartridge with bankswitching
# for assembler
# ld65 config file
@ -30,8 +30,23 @@ SEGMENTS {
BANK5: load = BANKROM5, type = ro;
BANK6: load = BANKROM6, type = ro;
BANK7: load = BANKROM7, type = ro;
ZEROPAGE: load = RAM, type = bss, define = yes;
DATA: load = RAM, type = bss, define = yes, offset = $0200;
ZEROPAGE: load = RAM, type = zp, define = yes;
DATA: load = RAM, type = rw, define = yes, offset = $0200;
BSS: load = RAM, type = bss, define = yes;
VECTOR: load = ROM, type = ro, offset = $3FFA;
VECTORS: load = ROM, type = ro, start = $FFFA;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

View File

@ -20,8 +20,8 @@ SEGMENTS {
CODE: load = ROM, type = ro, define = yes;
RODATA: load = ROM, type = ro, define = yes;
DATA: load = ROM, run = RAM, type = rw, define = yes;
FFF0: load = ROM, type = ro, offset = $3FF0;
VECTOR: load = ROM, type = ro, offset = $3FFA;
FFF0: load = ROM, type = ro, start = $FFF0;
VECTORS: load = ROM, type = ro, start = $FFFA;
BSS: load = RAM, type = bss, define = yes;
}
FEATURES {

View File

@ -23,8 +23,23 @@ SEGMENTS {
BANK1: load = BANKROM1, type = ro;
BANK2: load = BANKROM2, type = ro;
BANK3: load = BANKROM3, type = ro;
ZEROPAGE: load = RAM, type = bss, define = yes;
DATA: load = RAM, type = bss, define = yes, offset = $0200;
ZEROPAGE: load = RAM, type = zp, define = yes;
DATA: load = RAM, type = rw, define = yes, offset = $0200;
BSS: load = RAM, type = bss, define = yes;
VECTOR: load = ROM, type = ro, offset = $3FFA;
VECTORS: load = ROM, type = ro, start = $FFFA;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

View File

@ -19,8 +19,8 @@ SEGMENTS {
CODE: load = ROM, type = ro, define = yes;
RODATA: load = ROM, type = ro, define = yes;
DATA: load = ROM, run = RAM, type = rw, define = yes;
FFF0: load = ROM, type = ro, offset = $7FF0;
VECTOR: load = ROM, type = ro, offset = $7FFA;
FFF0: load = ROM, type = ro, start = $FFF0;
VECTORS: load = ROM, type = ro, start = $FFFA;
BSS: load = RAM, type = bss, define = yes;
}
FEATURES {

View File

@ -1,7 +1,7 @@
SYMBOLS {
__LOADADDR__: type = import;
__EXEHDR__: type = import;
__STACKSIZE__: type = weak, value = $0400; # 1k stack
__STACKSIZE__: type = weak, value = $0100;
}
MEMORY {
ZP: file = "", define = yes, start = $0002, size = $001A;

View File

@ -332,6 +332,7 @@ See the <url url="funcref.html" name="function reference"> for declaration and u
<item>_scroll
<item>_setcolor
<item>_setcolor_low
<item>waitvsync
</itemize>

View File

@ -30,7 +30,7 @@ information.
<sect>Binary format<p>
The standard binary output format generated by the linker for the Atari 5200 target
The binary output format generated by the linker for the Atari 5200 target
is a cartridge image. It is of course
possible to change this behaviour by using a modified startup file and linker
config.
@ -73,11 +73,22 @@ Special locations:
Programs containing Atari 5200 specific code may use the <tt/atari5200.h/ header file.
This also includes access to operating system locations (e.g. hardware shadow registers) by a structure called
"<tt/OS/".
The names are the usual ones you can find in system reference manuals. Example:
<tscreen><verb>
...
OS.sdmctl = 0x00; // screen off
OS.color4 = 14; // white frame
tics = OS.rtclok[1] // get ticks
...
</verb></tscreen>
<sect1>Atari 5200 specific functions<p>
<itemize>
<item>TBD.
<item>waitvsync
</itemize>
@ -208,10 +219,58 @@ you cannot use any of the following functions (and a few others):
<sect>Other hints<p>
<sect1>CAR format<p>
AtariROMMaker (<url url="https://www.wudsn.com/index.php/productions-atari800/tools/atarirommaker"> )
can be used to create a <tt/.CAR/ file from the binary ROM image cc65 generates.
This might be more convenient when working with emulators.
<sect1>Changing the splash screen<p>
The 5200 ROM displays a splash screen at startup with the name of the
game and the copyright year. The year information has a 'Year-2000'
problem, the first two digits are fixed in the ROM and are always "19".
<sect2>Changing the game name<p>
The runtime library provides a default game name which is "cc65
compiled". To change that, one has to link a file which puts data into
the "<tt/CARTNAME/" segment.
For reference, here's the default version used by the cc65 libary:
<tscreen><verb>
.export __CART_NAME__: absolute = 1
.macpack atari
.segment "CARTNAME"
scrcode " cc"
.byte '6' + 32, '5' + 32 ; use playfield 1
scrcode " compiled"
</verb></tscreen>
'<tt/__CART_NAME__/' needs to be defined in order that the linker is
satisfied and doesn't try to include the version of the runtime library.
20 bytes are available in the <tt/CARTNAME/ segment (one line) for the
game/program name.
<sect2>Changing the copyright year / changing the cartridge type<p>
The century is hard-coded to 1900 by the ROM.
There are two digits which can be changed. For example "92" will give
"1992" on the screen.
The default used by the runtime library is
<tscreen><verb>
.export __CART_YEAR__: absolute = 1
.segment "CARTYEAR"
.byte '9' + 32,'8' + 32 ; "98", using playfield 1
</verb></tscreen>
If the second byte of the year in the <tt/CARTYEAR/ segment is 255,
the cartridge is seen as a 'diagnostic' cartridge, and the splash
screen and most of the other startup initializations are bypassed.
<sect>License<p>

View File

@ -151,7 +151,7 @@ Here is a description of all the command line options:
Set the default for the CPU type. The option takes a parameter, which
may be one of
6502, 6502X, 65SC02, 65C02, 65816, sweet16, HuC6280, 4510
6502, 6502X, 6502DTV, 65SC02, 65C02, 65816, sweet16, HuC6280, 4510
<label id="option-create-dep">
@ -419,6 +419,8 @@ The assembler accepts
<tt><ref id=".P02" name=".P02"></tt> command was given).
<item>all valid 6502 mnemonics plus a set of illegal instructions when in
<ref id="6502X-mode" name="6502X mode">.
<item>all valid 6502DTV mnemonics when in 6502DTV mode (after the
<tt><ref id=".PDTV" name=".PDTV"></tt> command was given).
<item>all valid 65SC02 mnemonics when in 65SC02 mode (after the
<tt><ref id=".PSC02" name=".PSC02"></tt> command was given).
<item>all valid 65C02 mnemonics when in 65C02 mode (after the
@ -3153,6 +3155,12 @@ Here's a list of all control commands and a description, what they do:
(see <tt><ref id=".PC02" name=".PC02"></tt> command).
<sect1><tt>.IFPDTV</tt><label id=".IFPDTV"><p>
Conditional assembly: Check if the assembler is currently in 6502DTV mode
(see <tt><ref id=".PDTV" name=".PDTV"></tt> command).
<sect1><tt>.IFPSC02</tt><label id=".IFPSC02"><p>
Conditional assembly: Check if the assembler is currently in 65SC02 mode
@ -3585,6 +3593,14 @@ Here's a list of all control commands and a description, what they do:
<tt><ref id=".P4510" name=".P4510"></tt>
<sect1><tt>.PDTV</tt><label id=".PDTV"><p>
Enable the 6502DTV instruction set. This is a superset of the 6502
instruction set.
See: <tt><ref id=".P02" name=".P02"></tt>
<sect1><tt>.POPCPU</tt><label id=".POPCPU"><p>
Pop the last CPU setting from the stack, and activate it.
@ -3848,10 +3864,11 @@ Here's a list of all control commands and a description, what they do:
Switch the CPU instruction set. The command is followed by a string that
specifies the CPU. Possible values are those that can also be supplied to
the <tt><ref id="option--cpu" name="--cpu"></tt> command line option,
namely: 6502, 6502X, 65SC02, 65C02, 65816, 4510 and HuC6280.
namely: 6502, 6502X, 6502DTV, 65SC02, 65C02, 65816, 4510 and HuC6280.
See: <tt><ref id=".CPU" name=".CPU"></tt>,
<tt><ref id=".IFP02" name=".IFP02"></tt>,
<tt><ref id=".IFPDTV" name=".IFPDTV"></tt>,
<tt><ref id=".IFP816" name=".IFP816"></tt>,
<tt><ref id=".IFPC02" name=".IFPC02"></tt>,
<tt><ref id=".IFPSC02" name=".IFPSC02"></tt>,
@ -4586,6 +4603,7 @@ each supported CPU a constant similar to
CPU_SWEET16
CPU_HUC6280
CPU_4510
CPU_6502DTV
</verb></tscreen>
is defined. These constants may be used to determine the exact type of the
@ -4600,6 +4618,7 @@ another constant is defined:
CPU_ISET_SWEET16
CPU_ISET_HUC6280
CPU_ISET_4510
CPU_ISET_6502DTV
</verb></tscreen>
The value read from the <tt/<ref id=".CPU" name=".CPU">/ pseudo variable may

View File

@ -6,8 +6,9 @@
<url url="mailto:gregdk@users.sf.net" name="Greg King">
<abstract>
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
computers like the Commodore and Atari machines, but it is easily retargetable.
cc65 is a C compiler for 6502 targets. It supports several 6502-based home
computers such as the Commodore and Atari machines, but it easily is
retargetable.
</abstract>
<!-- Table of contents -->
@ -548,6 +549,8 @@ Here is a description of all the command line options:
<tag><tt/remap-zero/</tag>
Warn about a <tt/<ref id="pragma-charmap" name="#pragma charmap()">/
that changes a character's code number from/to 0x00.
<tag><tt/return-type/</tag>
Warn about no return statement in function returning non-void.
<tag><tt/struct-param/</tag>
Warn when passing structs by value.
<tag><tt/unknown-pragma/</tag>
@ -706,12 +709,13 @@ This cc65 version has some extensions to the ISO C standard.
places.
<p>
<item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/.
Both refer to the primary register that is used by the compiler to
evaluate expressions or return function results. <tt/__AX__/ is of
type <tt/unsigned int/ and <tt/__EAX__/ of type <tt/long unsigned int/
respectively. The pseudo variables may be used as lvalue and rvalue as
every other variable. They are most useful together with short
<item> There are three pseudo variables named <tt/__A__/, <tt/__AX__/ and
<tt/__EAX__/. They all refer to the primary register that is used
by the compiler to evaluate expressions or return function results.
<tt/__A__/ is of type <tt/unsigned char/, <tt/__AX__/ is of type
<tt/unsigned int/ and <tt/__EAX__/ of type <tt/long unsigned int/
respectively. The pseudo variables may be used as lvalue and rvalue
as every other variable. They are most useful together with short
sequences of assembler code. For example, the macro
<tscreen><verb>
@ -1045,26 +1049,39 @@ parameter with the <tt/#pragma/.
The <tt/#pragma/ understands the push and pop parameters as explained above.
<sect1><tt>#pragma bss-name (&lsqb;push,&rsqb; &lt;name&gt;)</tt><label id="pragma-bss-name"><p>
<sect1><tt>#pragma bss-name ([push, ]&lt;name>[ ,&lt;addrsize>])</tt><label id="pragma-bss-name"><p>
This pragma changes the name used for the BSS segment (the BSS segment
is used to store variables with static storage duration and no explicit
initializer). The argument is a string enclosed in double quotes.
This pragma changes the name used for the BSS segment (the BSS segment is
used to store variables with static storage duration and no explicit
initializers). The <tt/name/ argument is a string enclosed in quotation
marks.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
<tt/addrsize/ is an optional string that gives a hint about where the
<tt/name/ segment will be put in the CPU's address space. It describes the
width of address numbers that point into that segment. Only words that
are known to ca65 are allowed:
<enum>
<item>"zp", "zeropage", "direct"
<item>"abs", "absolute", "near", "default"
<item>"far"
<item>"long", "dword"
</enum>
Beware: The startup code will zero only the default BSS segment. If you
use another BSS segment, you have to do that yourself, otherwise
variables with static storage duration and no explicit initializer will
not have the value zero.
Note: The default linker configuration file maps only the standard segments.
If you use other segments, you must create a new linker configuration file.
The <tt/#pragma/ understands the push and pop parameters as explained above.
Beware: The start-up code will zero only the default BSS segment. If you use
another BSS segment, then you must do that yourself; otherwise, variables
with static storage duration and no explicit initializer will not have the
value zero.
Example:
The <tt/#pragma/ understands the push and pop parameters, as explained above.
Examples:
<tscreen><verb>
#pragma bss-name ("MyBSS")
#pragma bss-name (push, "MyBSS")
#pragma bss-name ("MyBSS", "zp")
</verb></tscreen>
@ -1120,21 +1137,33 @@ parameter with the <tt/#pragma/.
The <tt/#pragma/ understands the push and pop parameters as explained above.
<sect1><tt>#pragma code-name ([push,] &lt;name&gt;)</tt><label id="pragma-code-name"><p>
<sect1><tt>#pragma code-name ([push, ]&lt;name>[ ,&lt;addrsize>])</tt><label id="pragma-code-name"><p>
This pragma changes the name used for the CODE segment (the CODE segment
is used to store executable code). The argument is a string enclosed in
double quotes.
This pragma changes the name used for the CODE segment (the CODE segment is
used to store executable code). The <tt/name/ argument is a string enclosed
in quotation marks.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
<tt/addrsize/ is an optional string that gives a hint about where the
<tt/name/ segment will be put in the CPU's address space. It describes the
width of address numbers that point into that segment. Only words that
are known to ca65 are allowed:
<enum>
<item>"zp", "zeropage", "direct"
<item>"abs", "absolute", "near", "default"
<item>"far"
<item>"long", "dword"
</enum>
The <tt/#pragma/ understands the push and pop parameters as explained above.
Note: The default linker configuration file maps only the standard segments.
If you use other segments, you must create a new linker configuration file.
Example:
The <tt/#pragma/ understands the push and pop parameters, as explained above.
Examples:
<tscreen><verb>
#pragma code-name ("MyCODE")
#pragma code-name (push, "MyCODE")
#pragma code-name (push, "MyCODE", "far")
</verb></tscreen>
@ -1148,21 +1177,33 @@ parameter with the <tt/#pragma/.
The <tt/#pragma/ understands the push and pop parameters as explained above.
<sect1><tt>#pragma data-name ([push,] &lt;name&gt;)</tt><label id="pragma-data-name"><p>
<sect1><tt>#pragma data-name ([push, ]&lt;name>[ ,&lt;addrsize>])</tt><label id="pragma-data-name"><p>
This pragma changes the name used for the DATA segment (the DATA segment
is used to store initialized data). The argument is a string enclosed in
double quotes.
This pragma changes the name used for the DATA segment (the DATA segment is
used to store initialized data). The <tt/name/ argument is a string enclosed
in quotation marks.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
<tt/addrsize/ is an optional string that gives a hint about where the
<tt/name/ segment will be put in the CPU's address space. It describes the
width of address numbers that point into that segment. Only words that
are known to ca65 are allowed:
<enum>
<item>"zp", "zeropage", "direct"
<item>"abs", "absolute", "near", "default"
<item>"far"
<item>"long", "dword"
</enum>
The <tt/#pragma/ understands the push and pop parameters as explained above.
Note: The default linker configuration file maps only the standard segments.
If you use other segments, you must create a new linker configuration file.
Example:
The <tt/#pragma/ understands the push and pop parameters, as explained above.
Examples:
<tscreen><verb>
#pragma data-name ("MyDATA")
#pragma data-name (push, "MyDATA")
#pragma data-name ("MyDATA", "zeropage")
</verb></tscreen>
@ -1224,21 +1265,32 @@ parameter with the <tt/#pragma/.
The <tt/#pragma/ understands the push and pop parameters as explained above.
<sect1><tt>#pragma rodata-name ([push,] &lt;name&gt;)</tt><label id="pragma-rodata-name"><p>
<sect1><tt>#pragma rodata-name ([push, ]&lt;name>[ ,&lt;addrsize>])</tt><label id="pragma-rodata-name"><p>
This pragma changes the name used for the RODATA segment (the RODATA
segment is used to store readonly data). The argument is a string
enclosed in double quotes.
This pragma changes the name used for the RODATA segment (the RODATA segment
is used to store read-only data). The <tt/name/ argument is a string enclosed
in quotation marks.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
<tt/addrsize/ is an optional string that gives a hint about where the
<tt/name/ segment will be put in the CPU's address space. It describes the
width of address numbers that point into that segment. Only words that
are known to ca65 are allowed:
<enum>
<item>"zp", "zeropage", "direct"
<item>"abs", "absolute", "near", "default"
<item>"far"
<item>"long", "dword"
</enum>
The <tt/#pragma/ understands the push and pop parameters as explained above.
Note: The default linker configuration file maps only the standard segments.
If you use other segments, you must create a new linker configuration file.
Example:
The <tt/#pragma/ understands the push and pop parameters, as explained above.
Examples:
<tscreen><verb>
#pragma rodata-name ("MyRODATA")
#pragma rodata-name (push, "MyRODATA")
</verb></tscreen>

View File

@ -112,15 +112,17 @@ Here is a description of all the command line options:
<itemize>
<item>6502
<item>6502x
<item>6502dtv
<item>65sc02
<item>65c02
<item>huc6280
<item>4510
</itemize>
6502x is for the NMOS 6502 with unofficial opcodes. huc6280 is the CPU of
the PC engine. 4510 is the CPU of the Commodore C65. Support for the 65816
currently is not available.
6502x is for the NMOS 6502 with unofficial opcodes. 6502dtv is for the
emulated CPU of the C64DTV device. huc6280 is the CPU of the PC engine.
4510 is the CPU of the Commodore C65. Support for the 65816 currently
is not available.
<label id="option--formfeeds">
@ -251,7 +253,10 @@ for this CPU. Invalid opcodes are translated into <tt/.byte/ commands.
With the command line option <tt><ref id="option--cpu" name="--cpu"></tt>, the
disassembler may be told to recognize either the 65SC02 or 65C02 CPUs. The
latter understands the same opcodes as the former, plus 16 additional bit
manipulation and bit test-and-branch commands.
manipulation and bit test-and-branch commands. Using 6502x as CPU the illegal
opcodes of 6502 CPU are detected and displayed. 6502dtv setting recognizes the
emulated CPU instructons of the C64DTV device.
When disassembling 4510 code, due to handling of 16-bit wide branches, da65
can produce output that can not be re-assembled, when one or more of those

View File

@ -858,20 +858,21 @@ The functions described here are common for SEQ and VLIR structures.
<p>
<tt/struct filehandle *GetNxtDirEntry (void)/
<p>
These two functions are best suited for scanning the whole directory for particular files. Note that
the returned filehandles describe all file slots in the directory - even those with deleted files.
The return value can be obtained by casting both sides to <tt/unsigned/ - as in the <tt/SetNextFree/
function or read directly after a call to those two functions from <tt/r5/. The current sector number
is in <tt/r1/ and the sector data itself is in <tt/diskBlkBuf/.
Those two functions are best suited for scanning the whole directory for particular files. Note that
the returned filehandles describe all file slots in the directory -- even those with deleted files.
The return value is <tt/NULL/ if there are no more slots, or if there was a disk error. The
<tt/_oserror/ variable is non-zero if it was a disk error (see <tt>geos/gdisk.h</tt>). The current
directory track and sector numbers are in <tt/r1L/ and <tt/r1H/. The sector data itself is in
<tt/diskBlkBuf/.
<sect3>FindFile
<p>
<tt/char FindFile (char *fName)/
<p>
This function scans the whole directory for the given filename. It returns either 0 (success) or 5
(FILE_NOT_FOUND, defined in <tt/gdisk.h/) or any other fatal disk read error. After a successful
<tt/FindFile/ you will have <tt/struct filehandle/ at <tt/dirEntryBuf/ filled with the file's data and
other registers set as described in <tt/GetNxtDirEntry/.
This function scans the whole directory for the given filename. It returns either 0 (success), 5
(FILE_NOT_FOUND, defined in <tt>geos/gdisk.h</tt>), or any other fatal disk read error. After a successful
<tt/FindFile()/, you will have <tt/struct filehandle/ at <tt/dirEntryBuf/ filled with the file's data, and
other registers set as described in <tt/GetNxtDirEntry()/.
<sect3>FindFTypes
<p>

View File

@ -921,9 +921,8 @@ name="6502 binary relocation format specification">). It is defined like this:
}
</verb></tscreen>
The other format available is the Atari (xex) segmented file format, this is
the standard format used by Atari DOS 2.0 and upward file managers in the Atari
8-bit computers, and it is defined like this:
The other format available is the Atari segmented file format (xex), this is
the standard format used by Atari DOS 2.0 and upwards, and it is defined like this:
<tscreen><verb>
FILES {
@ -1010,7 +1009,8 @@ The <tt/CONDES/ feature has several attributes:
<tag><tt>segment</tt></tag>
This attribute tells the linker into which segment the table should be
placed. If the segment does not exist, it is created.
placed. If the segment does not exist in any object file, it is created
in the final object code.
<tag><tt>type</tt></tag>
@ -1059,7 +1059,7 @@ The <tt/CONDES/ feature has several attributes:
Without specifying the <tt/CONDES/ feature, the linker will not create any
tables, even if there are <tt/condes/ entries in the object files.
For more information see the <tt/.CONDES/ command in the <url
For more information, see the <tt/.CONDES/ command in the <url
url="ca65.html" name="ca65 manual">.
@ -1140,6 +1140,19 @@ The builtin config files do contain segments that have a special meaning for
the compiler and the libraries that come with it. If you replace the builtin
config files, you will need the following information.
<sect1>INIT<p>
The INIT segment is some kind of 'bss' segment since it contains
uninitialized data. Unlike <tt>.bss</tt> itself, its contents aren't
initialized to zero at program startup . It's mostly used by
constructors in the startup code. An example for the use of the INIT
segment is saving/restoring the zero page area used by cc65.
<sect1>LOWCODE<p>
For the LOWCODE segment, it is guaranteed that it won't be banked out, so it
is reachable at any time by interrupt handlers or similar.
<sect1>ONCE<p>
The ONCE segment is used for initialization code run only once before
@ -1147,11 +1160,6 @@ execution reaches main() - provided that the program runs in RAM. You
may for example add the ONCE segment to the heap in really memory
constrained systems.
<sect1>LOWCODE<p>
For the LOWCODE segment, it is guaranteed that it won't be banked out, so it
is reachable at any time by interrupt handlers or similar.
<sect1>STARTUP<p>
This segment contains the startup code which initializes the C software stack

View File

@ -105,6 +105,7 @@ declaration and usage.
<item>cbm_save
<item>cbm_write
<item>get_tv
<item>waitvsync
</itemize>

80
include/_atari5200os.h Normal file
View File

@ -0,0 +1,80 @@
/*****************************************************************************/
/* */
/* _atari5200os.h */
/* */
/* Internal include file, do not use directly */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef __ATARI5200OS_H
#define __ATARI5200OS_H
struct __os {
/*Page zero*/
unsigned char pokmsk; // = $00 System mask for POKEY IRQ enable
unsigned char rtclok[2]; // = $01,$02 Real time clock
unsigned char critic; // = $03 Critical section flag
unsigned char atract; // = $04 Attract mode counter
union {
struct {
unsigned char sdlstl; // = $05 Save display list LO
unsigned char sdlsth; // = $06 Save display list HI
};
void* sdlst; // = $05,$06 Display list shadow
};
unsigned char sdmctl; // = $07 DMACTL shadow
unsigned char pcolr0; // = $08 PM color 0
unsigned char pcolr1; // = $09 PM color 1
unsigned char pcolr2; // = $0A PM color 2
unsigned char pcolr3; // = $0B PM color 3
unsigned char color0; // = $0C PF color 0
unsigned char color1; // = $0D PF color 1
unsigned char color2; // = $0E PF color 2
unsigned char color3; // = $0F PF color 3
unsigned char color4; // = $10 PF color 4
unsigned char _free_1[0xEF]; // = $11-$FF User space
/*Stack*/
unsigned char stack[0x100]; // = $100-$1FF Stack
/*Page 2 OS variables*/
void (*vinter)(void); // = $200 Immediate IRQ vector
void (*vvblki)(void); // = $202 Immediate VBI vector
void (*vvblkd)(void); // = $204 Deferred VBI vector
void (*vdslst)(void); // = $206 DLI vector
void (*vkeybd)(void); // = $208 Keyboard IRQ vector
void (*vkeypd)(void); // = $20A Keyboard continuation vector
void (*vbrkky)(void); // = $20C Break key interrupt vector
void (*vbreak)(void); // = $20E BRK instruction interrupt vector
void (*vserin)(void); // = $210 Serial input ready vector
void (*vseror)(void); // = $212 Serial output data needed vector
void (*vseroc)(void); // = $214 Serial output completed vector
void (*vtimr1)(void); // = $216 POKEY timer 1 IRQ vector
void (*vtimr2)(void); // = $218 POKEY timer 2 IRQ vector
void (*vtimr4)(void); // = $21A POKEY timer 4 IRQ vector
};
#endif

View File

@ -6,10 +6,11 @@
/* */
/* */
/* */
/* (C) 2000-2019 Mark Keates <markk@dendrite.co.uk> */
/* (C) 2000-2021 Mark Keates <markk@dendrite.co.uk> */
/* Freddy Offenga <taf_offenga@yahoo.com> */
/* Christian Groessler <chris@groessler.org> */
/* Bill Kendrick <nbs@sonic.net> */
/* et al. */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -219,7 +220,7 @@
/* Color register functions */
/*****************************************************************************/
extern void __fastcall__ _setcolor (unsigned char color_reg, unsigned char hue, unsigned char luminace);
extern void __fastcall__ _setcolor (unsigned char color_reg, unsigned char hue, unsigned char luminance);
extern void __fastcall__ _setcolor_low (unsigned char color_reg, unsigned char color_value);
extern unsigned char __fastcall__ _getcolor (unsigned char color_reg);
@ -227,6 +228,7 @@ extern unsigned char __fastcall__ _getcolor (unsigned char color_reg);
/* Other screen functions */
/*****************************************************************************/
extern void waitvsync (void); /* wait for start of next frame */
extern int __fastcall__ _graphics (unsigned char mode); /* mode value same as in BASIC */
extern void __fastcall__ _scroll (signed char numlines);
/* numlines > 0 scrolls up */

View File

@ -35,7 +35,7 @@
/* Check for errors */
/* check for errors */
#if !defined(__ATARI5200__)
# error This module may only be used when compiling for the Atari 5200!
#endif
@ -46,14 +46,14 @@
/* the addresses of the static drivers */
extern void atr5200std_joy[]; /* referred to by joy_static_stddrv[] */
/* Masks for joy_read */
/* masks for joy_read */
#define JOY_UP_MASK 0x01
#define JOY_DOWN_MASK 0x02
#define JOY_LEFT_MASK 0x04
#define JOY_RIGHT_MASK 0x08
#define JOY_BTN_1_MASK 0x10
/* Character codes */
/* character codes */
#define CH_ULCORNER 0x0B /* '+' sign */
#define CH_URCORNER 0x0B
#define CH_LLCORNER 0x0B
@ -65,7 +65,11 @@ extern void atr5200std_joy[]; /* referred to by joy_static_stddrv[] */
#define AT_NTSC 0
#define AT_PAL 1
/* Define hardware */
/* Define variables used by the OS*/
#include <_atari5200os.h>
#define OS (*(struct __os*)0x0000)
/* define hardware */
#include <_gtia.h>
#define GTIA_READ (*(struct __gtia_read*)0xC000)
#define GTIA_WRITE (*(struct __gtia_write*)0xC000)
@ -89,5 +93,8 @@ extern void atr5200std_joy[]; /* referred to by joy_static_stddrv[] */
*/
#define _bordercolor(color) 0
/* End of atari5200.h */
/* wait for start of next frame */
extern void waitvsync (void);
/* end of atari5200.h */
#endif

View File

@ -166,7 +166,7 @@ unsigned char get_tv (void);
unsigned char __fastcall__ kbrepeat (unsigned char mode);
/* Changes which keys have automatic repeat. */
#if !defined(__CBM610__) && !defined(__PET__)
#if !defined(__CBM610__)
void waitvsync (void);
/* Wait for the start of the next video field. */
#endif
@ -191,6 +191,8 @@ unsigned char cbm_k_acptr (void);
unsigned char cbm_k_basin (void);
void __fastcall__ cbm_k_bsout (unsigned char C);
unsigned char __fastcall__ cbm_k_chkin (unsigned char FN);
unsigned char cbm_k_chrin (void);
void __fastcall__ cbm_k_chrout (unsigned char C);
void __fastcall__ cbm_k_ciout (unsigned char C);
unsigned char __fastcall__ cbm_k_ckout (unsigned char FN);
void cbm_k_clall (void);
@ -295,7 +297,15 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn,
/* Reads one directory line into cbm_dirent structure.
** Returns 0 if reading directory-line was successful.
** Returns non-zero if reading directory failed, or no more file-names to read.
** Returns 2 on last line. Then, l_dirent->size = the number of "blocks free."
** Returns 2 on last line. Then, l_dirent->size = the number of "blocks free",
** "blocks used", or "mb free". Return codes:
** 0 = read file-name
** 1 = couldn't read directory
** 2 = read "blocks free", "blocks used", or "mb free"
** 3 = couldn't find start of file-name
** 4 = couldn't find end of file-name
** 5 = couldn't read file-type
** 6 = premature end of file
*/
void __fastcall__ cbm_closedir (unsigned char lfn);

View File

@ -83,46 +83,31 @@ extern struct _timezone {
#if defined(__ATARI__)
/* The clock depends on the video standard, so read it at runtime */
unsigned _clocks_per_sec (void);
# define CLK_TCK _clocks_per_sec()
# define CLOCKS_PER_SEC _clocks_per_sec()
#elif defined(__ATARI5200__)
# define CLK_TCK 60 /* POSIX */
# define CLOCKS_PER_SEC 60 /* ANSI */
#if defined(__ATARI5200__)
# define CLOCKS_PER_SEC 60
#elif defined(__ATMOS__)
# define CLK_TCK 100 /* POSIX */
# define CLOCKS_PER_SEC 100 /* ANSI */
# define CLOCKS_PER_SEC 100
#elif defined(__CBM__)
# if defined(__CBM510__) || defined(__CBM610__)
/* The 510/610 gets its clock from the AC current */
# define CLK_TCK 50 /* POSIX */
# define CLOCKS_PER_SEC 50 /* ANSI */
# define CLOCKS_PER_SEC 50
# else
# define CLK_TCK 60 /* POSIX */
# define CLOCKS_PER_SEC 60 /* ANSI */
# define CLOCKS_PER_SEC 60
# endif
#elif defined(__NES__)
# define CLK_TCK 50 /* POSIX */
# define CLOCKS_PER_SEC 50 /* ANSI */
# define CLOCKS_PER_SEC 50
#elif defined(__PCE__)
# define CLK_TCK 60 /* POSIX */
# define CLOCKS_PER_SEC 60 /* ANSI */
# define CLOCKS_PER_SEC 60
#elif defined(__GAMATE__)
# define CLK_TCK 135 /* POSIX */ /* FIXME */
# define CLOCKS_PER_SEC 135 /* ANSI */ /* FIXME */
# define CLOCKS_PER_SEC 135 /* FIXME */
#elif defined(__GEOS__)
# define CLK_TCK 1 /* POSIX */
# define CLOCKS_PER_SEC 1 /* ANSI */
#elif defined(__LYNX__)
/* The clock-rate depends on the video scan-rate;
** so, read it at run-time.
*/
extern clock_t _clk_tck (void);
# define CLK_TCK _clk_tck()
# define CLOCKS_PER_SEC _clk_tck()
# define CLOCKS_PER_SEC 1
#else
/* Read the clock rate at runtime */
clock_t _clocks_per_sec (void);
# define CLOCKS_PER_SEC _clocks_per_sec()
#endif
#define CLK_TCK CLOCKS_PER_SEC
#define CLOCK_REALTIME 0
@ -149,6 +134,3 @@ int __fastcall__ clock_settime (clockid_t clock_id, const struct timespec *tp);
/* End of time.h */
#endif

View File

@ -133,8 +133,7 @@ MKINC = $(GEOS) \
TARGETUTIL = apple2 \
apple2enh \
atari \
geos-apple
atari
GEOSDIRS = common \
conio \

View File

@ -19,11 +19,14 @@
.segment "ONCE"
initprompt:
; Set prompt <> ']' to let DOS 3.3 know that we're
; not in Applesoft immediate mode and thus keep it
; from scanning our device I/O for DOS commands.
; Set prompt <> ']' and currently executed Applesoft
; line number hibyte <> $FF to let DOS 3.3 (at $A65E)
; know that we're not in Applesoft immediate mode and
; thus keep it from scanning our device I/O for DOS
; commands.
lda #$80 ; Same value used at $D52C
sta PROMPT
sta CURLIN+1 ; Any value <> $FF will do
rts
.code

View File

@ -1,9 +1,17 @@
DEPS += ../libwrk/$(TARGET)/loader.d
DEPS += ../libwrk/$(TARGET)/convert.d \
../libwrk/$(TARGET)/loader.d
../libwrk/$(TARGET)/convert.o: $(SRCDIR)/targetutil/convert.c | ../libwrk/$(TARGET)
$(COMPILE_recipe)
../libwrk/$(TARGET)/loader.o: $(SRCDIR)/targetutil/loader.s | ../libwrk/$(TARGET)
$(ASSEMBLE_recipe)
../target/$(TARGET)/util/convert.system: ../libwrk/$(TARGET)/convert.o ../lib/$(TARGET).lib | ../target/$(TARGET)/util
$(LD65) -o $@ -C $(TARGET)-system.cfg $^
../target/$(TARGET)/util/loader.system: ../libwrk/$(TARGET)/loader.o $(SRCDIR)/targetutil/loader.cfg | ../target/$(TARGET)/util
$(LD65) -o $@ -C $(filter %.cfg,$^) $(filter-out %.cfg,$^)
$(TARGET): ../target/$(TARGET)/util/loader.system
$(TARGET): ../target/$(TARGET)/util/convert.system \
../target/$(TARGET)/util/loader.system

View File

@ -3,7 +3,7 @@
; originally by Ullrich von Bassewitz and Sidney Cadot
;
; clock_t clock (void);
; unsigned _clocks_per_sec (void);
; clock_t _clocks_per_sec (void);
;
.export _clock, __clocks_per_sec
@ -30,8 +30,10 @@
.proc __clocks_per_sec
ldx #$00 ; Clear high byte of return value
lda PAL ; use hw register, PALNTS is only supported on XL/XE ROM
ldx #$00 ; Clear byte 1 of return value
stx sreg ; Clear byte 2 of return value
stx sreg+1 ; Clear byte 3 of return value
lda PAL ; Use hw register, PALNTS is only supported on XL/XE ROM
and #$0e
bne @NTSC
lda #50

View File

@ -1,7 +1,7 @@
;
; Christian Groessler, June-2016
;
; unsigned char doesclrscr(void);
; unsigned char doesclrscrafterexit (void);
;
; returns 0/1 if after program termination the screen isn't/is cleared
;

View File

@ -11,6 +11,7 @@
SHRAM_HANDLERS = 1
.include "atari.inc"
.include "romswitch.inc"
.import __CHARGEN_START__
.export set_VTIMR1_handler

View File

@ -11,6 +11,7 @@
SHRAM_HANDLERS = 1
.include "atari.inc"
.include "romswitch.inc"
.import __CHARGEN_START__
.export set_VTIMR2_handler

15
libsrc/atari/waitvsync.s Normal file
View File

@ -0,0 +1,15 @@
;
; Written by Christian Groessler <chris@groessler.org>
;
; void waitvsync (void);
;
.include "atari.inc"
.export _waitvsync
.proc _waitvsync
lda RTCLOK+2
@lp: cmp RTCLOK+2
beq @lp
rts
.endproc

View File

@ -2,7 +2,6 @@
; from Atari computer version by Christian Groessler, 2014
;
; clock_t clock (void);
; unsigned _clocks_per_sec (void);
;
.export _clock

View File

@ -13,7 +13,6 @@
.import zerobss, copydata
.include "zeropage.inc"
.include "atari5200.inc"
start:

View File

@ -0,0 +1,15 @@
;
; Written by Christian Groessler <chris@groessler.org>
;
; void waitvsync (void);
;
.include "atari5200.inc"
.export _waitvsync
.proc _waitvsync
lda RTCLOK+1
@lp: cmp RTCLOK+1
beq @lp
rts
.endproc

View File

@ -7,7 +7,7 @@
;
.export _cputcxy, _cputc
.export setscrptr, putchar
.export setscrptr, cputdirect, putchar
.constructor initcputc
.import rvs
.import popax
@ -32,13 +32,13 @@ _cputc: cmp #$0D ; CR?
rts
L1: cmp #$0A ; LF?
bne output
bne cputdirect
inc CURS_Y ; Newline
rts
; Output the character, then advance the cursor position
output:
cputdirect:
jsr putchar
advance:

View File

@ -20,18 +20,19 @@
sta ptr3
stx ptr3+1 ; save count as result
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; Remember -count-1
inx
stx ptr2+1
tax
inx
stx ptr2 ; save count with each byte incremented separately
jsr popptr1 ; get buf
jsr popax ; get fd and discard
L1: inc ptr2
L1: dec ptr2
bnz L2
inc ptr2+1
dec ptr2+1
bze L9 ; no more room in buf
; If there are no more characters in BASIC's input buffer, then get a line from

View File

@ -17,17 +17,17 @@
sta ptr3
stx ptr3+1 ; save count as result
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; Remember -count-1
inx
stx ptr2+1
tax
inx
stx ptr2 ; save count with each byte incremented separately
jsr popptr1 ; get buf
jsr popax ; get fd and discard
L1: inc ptr2
L1: dec ptr2
bne L2
inc ptr2+1
dec ptr2+1
beq L9
L2: ldy #0
lda (ptr1),y

View File

@ -22,7 +22,7 @@
MOUSE_SPR = 0 ; Sprite used for the mouse
MOUSE_SPR_MEM = $0E00 ; Memory location
MOUSE_SPR_MASK = $01 .shl MOUSE_SPR ; Positive mask
MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask
MOUSE_SPR_NMASK = .lobyte(.bitnot 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

View File

@ -13,7 +13,6 @@
.importzp ST
.include "zeropage.inc"
.include "plus4.inc"
; ------------------------------------------------------------------------
; Startup code

View File

@ -13,7 +13,6 @@
.importzp ST
.include "zeropage.inc"
.include "c64.inc"
; ------------------------------------------------------------------------

View File

@ -23,7 +23,7 @@
; of the sprite used for the mouse. All others depend on this 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
MOUSE_SPR_NMASK = .lobyte(.bitnot 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

View File

@ -2,14 +2,16 @@
; Ullrich von Bassewitz, 03.06.1999
;
; unsigned char cbm_k_basin (void);
; unsigned char cbm_k_chrin (void);
;
.include "cbm.inc"
.export _cbm_k_basin
.export _cbm_k_basin, _cbm_k_chrin
_cbm_k_basin:
_cbm_k_chrin:
jsr BASIN
ldx #0 ; Clear high byte
rts

View File

@ -2,10 +2,12 @@
; Ullrich von Bassewitz, 03.06.1999
;
; void __fastcall__ cbm_k_bsout (unsigned char C);
; void __fastcall__ cbm_k_chrout (unsigned char C);
;
.include "cbm.inc"
.export _cbm_k_bsout
.export _cbm_k_bsout, _cbm_k_chrout
_cbm_k_bsout = BSOUT
_cbm_k_bsout := BSOUT
_cbm_k_chrout := CHROUT

View File

@ -6,6 +6,7 @@
/* 2009-10-10 -- Version 0.3 */
/* 2011-04-07 -- Version 0.4, groepaz */
/* 2011-04-14 -- Version 0.5, Greg King */
/* 2021-02-15 -- Version 0.6, Greg King */
/* Tested with floppy-drive and IDE64 devices. */
/* Not tested with messed (buggy) directory listings. */
@ -29,7 +30,7 @@ unsigned char cbm_opendir (unsigned char lfn, unsigned char device, ...)
va_list ap;
const char* name = "$";
/* The name used in cbm_open may optionally be passed */
/* The name used in cbm_open() optionally may be passed */
if (__argsize__ == 4) {
va_start (ap, device);
name = va_arg (ap, const char*);
@ -76,9 +77,10 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_d
byte = cbm_k_basin();
switch (byte) {
/* "B" BLOCKS FREE. */
/* "B" BLOCKS FREE/USED. */
/* "M" MB FREE. */
case 'b':
case 'm':
/* Read until end; careless callers might call us again. */
while (!cbm_k_readst()) {
cbm_k_basin();
@ -168,7 +170,6 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_d
}
rv = 0;
goto ret_val;
}
}

View File

@ -45,11 +45,11 @@
_cbm_read:
eor #$FF
sta ptr1
txa
eor #$FF
sta ptr1+1 ; Save -size-1
inx
stx ptr1+1
tax
inx
stx ptr1 ; Save size with both bytes incremented separately.
jsr popax
sta ptr2
@ -92,9 +92,9 @@ _cbm_read:
bne @L3
inc ptr3+1 ; ++bytesread;
@L3: inc ptr1
@L3: dec ptr1
bne @L1
inc ptr1+1
dec ptr1+1
bne @L1
@L4: jsr CLRCH

View File

@ -39,11 +39,11 @@
_cbm_write:
sta ptr3
stx ptr3+1 ; Save size
eor #$FF
sta ptr1
txa
eor #$FF
sta ptr1+1 ; Save -size-1
inx
stx ptr1+1
tax
inx
stx ptr1 ; Save size with both bytes incremented separately
jsr popax
sta ptr2
@ -69,9 +69,9 @@ _cbm_write:
@L2: jsr BSOUT ; cbm_k_bsout (A);
@L3: inc ptr1 ; --size;
@L3: dec ptr1 ; --size;
bne @L1
inc ptr1+1
dec ptr1+1
bne @L1
jsr CLRCH

View File

@ -106,9 +106,9 @@
; Decrement the count
@L3: inc ptr2
@L3: dec ptr2
bne @L0
inc ptr2+1
dec ptr2+1
bne @L0
beq done ; Branch always

View File

@ -1,5 +1,7 @@
/*
** Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
** Based on code by Groepaz.
** 2012-05-30, Ullrich von Bassewitz
** 2021-02-15, Greg King
*/
@ -52,11 +54,13 @@ struct dirent* __fastcall__ readdir (register DIR* dir)
/* Bump the directory offset and include the bytes for line-link and size */
dir->off += count + 4;
/* End of directory is reached if the buffer contains "blocks free". It is
** sufficient here to check for the leading 'b'. buffer will contain at
** least one byte if we come here.
/* End of directory is reached if the buffer contains "blocks free/used" or
** "mb free.". It is sufficient here to check for the leading 'b' and 'm'.
** buffer will contain at least one byte if we come here.
*/
if (buffer[0] == 'b') {
switch (buffer[0]) {
case 'b':
case 'm':
goto exitpoint;
}
@ -67,7 +71,6 @@ struct dirent* __fastcall__ readdir (register DIR* dir)
b = buffer;
while (i < count) {
switch (s) {
case 0:
/* Searching for start of file name */
if (*b == '"') {
@ -127,6 +130,3 @@ struct dirent* __fastcall__ readdir (register DIR* dir)
exitpoint:
return 0;
}

View File

@ -21,11 +21,11 @@
.proc rwcommon
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; Remember -count-1
inx
stx ptr2+1
tax
inx
stx ptr2 ; Save count with each byte incremented separately
jsr popptr1 ; Get buf to ptr1, Y=0 by call

View File

@ -83,9 +83,9 @@
; Decrement count
@L2: inc ptr2
@L2: dec ptr2
bne @L0
inc ptr2+1
dec ptr2+1
bne @L0
; Wrote all chars or disk full. Close the output channel

View File

@ -24,7 +24,7 @@
MOUSE_SPR = 0 ; Sprite used for the mouse
MOUSE_SPR_MEM = $F400 ; Memory location
MOUSE_SPR_MASK = $01 .shl MOUSE_SPR ; Positive mask
MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask
MOUSE_SPR_NMASK = .lobyte(.bitnot 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

View File

@ -17,22 +17,22 @@
.proc _getcwd
; Remember -size-1 because this simplifies the following loop
; Remember size with each byte incremented because this simplifies the following loop
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1
inx
stx ptr2+1
tax
inx
stx ptr2 ; Save size with each byte incremented separately
jsr popptr1 ; Get buf to ptr1
; Copy __cwd to the given buffer checking the length
; ldy #$00 is guaranteed by popptr1
loop: inc ptr2
loop: dec ptr2
bne @L1
inc ptr2+1
dec ptr2+1
beq overflow
; Copy one character, end the loop if the zero terminator is reached. We

View File

@ -10,14 +10,14 @@
_memcmp:
; Calculate (-count-1) and store it into ptr3. This is some overhead here but
; saves time in the compare loop
; Calculate a special count, and store it into ptr3. That is some overhead here,
; but saves time in the compare loop
eor #$FF
sta ptr3
txa
eor #$FF
sta ptr3+1
inx
stx ptr3+1
tax
inx
stx ptr3 ; Save count with each byte incremented separately
; Get the pointer parameters
@ -29,12 +29,12 @@ _memcmp:
; Loop initialization
;ldy #$00 ; Initialize pointer (Y=0 guaranteed by popptr1)
ldx ptr3 ; Load low counter byte into X
ldx ptr3 ; Load inner counter byte into .X
; Head of compare loop: Test for the end condition
Loop: inx ; Bump low byte of (-count-1)
beq BumpHiCnt ; Jump on overflow
Loop: dex
beq BumpHiCnt ; Jump on end of inner count
; Do the compare
@ -50,10 +50,10 @@ Comp: lda (ptr1),y
inc ptr2+1
bne Loop ; Branch always (pointer wrap is illegal)
; Entry on low counter byte overflow
; Entry on inner loop end
BumpHiCnt:
inc ptr3+1 ; Bump high byte of (-count-1)
dec ptr3+1
bne Comp ; Jump if not done
jmp return0 ; Count is zero, areas are identical
@ -67,4 +67,3 @@ NotEqual:
Greater:
ldx #$01 ; Make result positive
rts

View File

@ -11,11 +11,11 @@
.macpack cpu
_strncat:
eor #$FF ; one's complement to count upwards
sta tmp1
txa
eor #$FF
sta tmp2
inx
stx tmp2
tax
inx
stx tmp1 ; save count with each byte incremented separately
jsr popptr1 ; get src
@ -49,9 +49,9 @@ L2: sty ptr2
L3: ldy #0
ldx tmp1 ; low counter byte
L4: inx
L4: dex
bne L5
inc tmp2
dec tmp2
beq L6 ; jump if done
L5: lda (ptr1),y
sta (ptr2),y

View File

@ -10,11 +10,11 @@
.proc _strncpy
eor #$FF
sta tmp1
txa
eor #$FF
sta tmp2 ; Store -size - 1
inx
stx tmp2
tax
inx
stx tmp1 ; save count with each byte incremented separately
jsr popptr1 ; get src
jsr popax ; get dest
@ -24,11 +24,11 @@
; Copy src -> dest up to size bytes
ldx tmp1 ; Load low byte of ones complement of size
ldx tmp1
ldy #$00
L1: inx
L1: dex
bne L2
inc tmp2
dec tmp2
beq L9
L2: lda (ptr1),y ; Copy one character
@ -42,8 +42,8 @@ L2: lda (ptr1),y ; Copy one character
; Fill the remaining bytes.
L3: inx ; Counter low byte
beq L6 ; Branch on overflow
L3: dex ; Counter low byte
beq L6
L4: sta (ptr2),y ; Clear one byte
L5: iny ; Bump pointer
bne L3
@ -52,7 +52,7 @@ L5: iny ; Bump pointer
; Bump the counter high byte
L6: inc tmp2
L6: dec tmp2
bne L4
; Done, return dest

View File

@ -15,17 +15,11 @@
_strnicmp:
_strncasecmp:
; Convert the given counter value in a/x from a downward counter into an
; upward counter, so we can increment the counter in the loop below instead
; of decrementing it. This adds some overhead now, but is cheaper than
; executing a more complex test in each iteration of the loop. We do also
; correct the value by one, so we can do the test on top of the loop.
eor #$FF
sta ptr3
txa
eor #$FF
sta ptr3+1
inx
stx ptr3+1
tax
inx
stx ptr3 ; save count with each byte incremented separately
; Get the remaining arguments
@ -40,8 +34,8 @@ _strncasecmp:
; Start of compare loop. Check the counter.
Loop: inc ptr3
beq IncHi ; increment high byte
Loop: dec ptr3 ; decrement high byte
beq IncHi
; Compare a byte from the strings
@ -79,7 +73,7 @@ L2: ldx tmp1
; Increment hi byte
IncHi: inc ptr3+1
IncHi: dec ptr3+1
bne Comp ; jump if counter not zero
; Exit code if strings are equal. a/x not set

View File

@ -47,12 +47,12 @@ outdesc: ; Static outdesc structure
out: jsr popax ; count
sta ptr2
eor #$FF
sta outdesc+6
txa
sta ptr2+1
eor #$FF
sta outdesc+7
stx ptr2+1
inx
stx outdesc+7
tax
inx
stx outdesc+6
jsr popptr1 ; buf
@ -74,7 +74,7 @@ out: jsr popax ; count
; Loop outputting characters
@L1: inc outdesc+6
@L1: dec outdesc+6
beq @L4
@L2: ldy tmp1
lda (ptr1),y
@ -85,7 +85,7 @@ out: jsr popax ; count
jsr _cputc
jmp @L1
@L4: inc outdesc+7
@L4: dec outdesc+7
bne @L2
rts

View File

@ -51,7 +51,7 @@ next: inx
jsr closecmdchannel
ldx tmp2
; As we had to reference ST above anyway, we can do so, as well,
; As we had to reference STATUS above anyway, we can do so, as well,
; here too (instead of calling READST).
lda STATUS

View File

@ -1,14 +0,0 @@
DEPS += ../libwrk/$(TARGET)/convert.d
../libwrk/$(TARGET)/convert.o: TARGET = apple2enh
../libwrk/$(TARGET)/convert.o: $(SRCDIR)/targetutil/convert.c | ../libwrk/$(TARGET)
$(COMPILE_recipe)
../lib/apple2enh.lib:
@$(MAKE) --no-print-directory apple2enh
../target/$(TARGET)/util/convert.system: ../libwrk/$(TARGET)/convert.o ../lib/apple2enh.lib | ../target/$(TARGET)/util
$(LD65) -o $@ -C apple2enh-system.cfg $^
$(TARGET): ../target/$(TARGET)/util/convert.system

View File

@ -13,6 +13,10 @@
.include "geossym.inc"
_CalcBlksFree:
lda #<curDirHead
ldx #>curDirHead
sta r5L
stx r5H
jsr CalcBlksFree
stx __oserror
lda r4L

View File

@ -94,11 +94,12 @@ _read:
; popax - fd, must be == to the above one
; return -1+__oserror or number of bytes read
eor #$ff
sta ptr1
txa
eor #$ff
sta ptr1+1 ; -(# of bytes to read)-1
inx
stx ptr1+1
tax
inx
stx ptr1 ; save count with each byte incremented separately
jsr popax
sta ptr2
stx ptr2+1 ; buffer ptr
@ -152,9 +153,9 @@ _read:
beq @done ; yes, we're done
jmp __mappederrno ; no, we're screwed
@L3: inc ptr1 ; decrement the count
@L3: dec ptr1 ; decrement the count
bne @L0
inc ptr1+1
dec ptr1+1
bne @L0
@done:

View File

@ -1,11 +1,11 @@
;
; Maciej 'YTM/Alliance' Witkowiak
; 1999-10-26, Maciej 'YTM/Alliance' Witkowiak
; 2020-10-29, Greg King
;
; 26.10.99
; struct filehandle* Get1stDirEntry (void);
.import __oserror
.import __oserror, return0
.export _Get1stDirEntry
.include "diskdrv.inc"
@ -14,6 +14,10 @@
_Get1stDirEntry:
jsr Get1stDirEntry
stx __oserror
txa
bne L1 ; jump if disk error
lda r5L
ldx r5H
rts
L1: jmp return0 ; return NULL if not valid entry

View File

@ -1,11 +1,11 @@
;
; Maciej 'YTM/Alliance' Witkowiak
; 1999-10-26, Maciej 'YTM/Alliance' Witkowiak
; 2020-10-29, Greg King
;
; 26.10.99
; struct filehandle* GetNxtDirEntry (void);
.import __oserror
.import __oserror, return0
.export _GetNxtDirEntry
.include "diskdrv.inc"
@ -14,6 +14,12 @@
_GetNxtDirEntry:
jsr GetNxtDirEntry
stx __oserror
txa
bne L1 ; jump if disk error
tya
bne L1 ; jump when no more entries
lda r5L
ldx r5H
rts
L1: jmp return0 ; return NULL if not valid entry

View File

@ -2,18 +2,14 @@
; 2003-04-13, Ullrich von Bassewitz
; 2012-02-06, Greg King
;
; #include <time.h>
;
; typedef unsigned long int clock_t;
; clock_t _clk_tck(void);
; #define CLOCKS_PER_SEC _clk_tck()
; clock_t clock (void);
; clock_t _clocks_per_sec (void);
;
; clk_tck()'s test-values are based on the numbers in "set_tv.s".
; clocks_per_sec()'s test-values are based on the numbers in "set_tv.s".
; If you change the numbers there, then change them here, too.
;
.export _clock, __clk_tck, clock_count
.export _clock, __clocks_per_sec, clock_count
.interruptor update_clock, 2 ; (low priority)
.constructor init_clock
@ -42,7 +38,7 @@
;-----------------------------------------------------------------------------
; Return the number of clock ticks in one second.
;
__clk_tck:
__clocks_per_sec:
ldx #$00 ; >50, >60, >75
ldy PBKUP
lda #<75

View File

@ -50,16 +50,15 @@ LINEDIST = $20 ; Offset in video RAM between two lines
ldx #>load_addr
sta load
stx load+1
lda #<load_size
eor #$FF
sta count ; store (-size - 1)
lda #>load_size
eor #$FF
sta count+1
L1: inc count ; pre-count one's-complement upwards
ldx #(<load_size) + 1
stx count
ldx #(>load_size) + 1
stx count+1 ; save size with each byte incremented separately
L1: dec count
bnz L2
inc count+1
dec count+1
bze L3
L2: jsr GETCHAR ; (doesn't change .Y)
sta (load),y

View File

@ -12,7 +12,6 @@
.include "zeropage.inc"
.include "pet.inc"
.include "../cbm/cbm.inc"
; ------------------------------------------------------------------------
; Startup code

16
libsrc/pet/waitvsync.s Normal file
View File

@ -0,0 +1,16 @@
;
; Written by Robin Harbron, requires 12" monitor
;
; void waitvsync (void);
;
.export _waitvsync
.include "pet.inc"
_waitvsync:
@l1:
lda VIA_PB
and #%00100000
bne @l1
rts

View File

@ -198,5 +198,3 @@ irqcount: .byte 0
.segment "INIT"
zpsave: .res zpspace

View File

@ -78,5 +78,3 @@ not_dma:
.word nmi
.word reset32kcode
.word irq

View File

@ -12,7 +12,6 @@
.import __MAIN_START__, __MAIN_SIZE__
.include "zeropage.inc"
.include "telestrat.inc"
; ------------------------------------------------------------------------
; Place the startup code in a special segment.

17
libsrc/telestrat/kbhit.s Normal file
View File

@ -0,0 +1,17 @@
;
; Jede, 2021-02-01
;
; int kbhit (void);
;
.export _kbhit
.include "telestrat.inc"
_kbhit:
BRK_TELEMON XRD0
ldx #$00
txa
rol
eor #$01
rts

View File

@ -13,11 +13,11 @@
sta ptr3
stx ptr3+1 ; save count as result
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; remember -count-1
inx
stx ptr2+1
tax
inx
stx ptr2 ; save count with each byte incremented separately
jsr popptr1 ; get buf
jsr popax ; get fd and discard
@ -51,9 +51,9 @@ next:
rts
L1: inc ptr2
L1: dec ptr2
bne L2
inc ptr2+1
dec ptr2+1
beq L9
L2: ldy #0
lda (ptr1),y

View File

@ -13,7 +13,6 @@
.importzp ST
.include "zeropage.inc"
.include "vic20.inc"
; ------------------------------------------------------------------------
; Startup code

View File

@ -31,6 +31,7 @@
/* Workaround missing clock stuff */
#ifdef __APPLE2__
# define clock() 0
# undef CLK_TCK
# define CLK_TCK 1
#endif

View File

@ -1,7 +1,7 @@
/*****************************************************************************\
** plasma test program for cc65. **
** **
** (w)2001 by groepaz/hitmen **
** (w)2001 by groepaz **
** **
** Cleanup and porting by Ullrich von Bassewitz. **
** **
@ -54,7 +54,6 @@
#pragma static-locals (1);
static const unsigned char sinustable[0x100] = {
0x80, 0x7d, 0x7a, 0x77, 0x74, 0x70, 0x6d, 0x6a,
0x67, 0x64, 0x61, 0x5e, 0x5b, 0x58, 0x55, 0x52,
@ -131,8 +130,6 @@ static void doplasma (register unsigned char* scrn)
}
}
static void makechar (void)
{
static const unsigned char bittab[8] = {
@ -147,7 +144,7 @@ static void makechar (void)
for (i = 0; i < 8; ++i){
b = 0;
for (ii = 0; ii < 8; ++ii) {
if ((rand() & 0xFF) > s) {
if ((rand() & 0xFFu) > s) {
b |= bittab[ii];
}
}

View File

@ -416,6 +416,16 @@ void DoConditionals (void)
CalcOverallIfCond ();
break;
case TOK_IFPDTV:
D = AllocIf (".IFPDTV", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502DTV);
}
ExpectSep ();
CalcOverallIfCond ();
break;
case TOK_IFPSC02:
D = AllocIf (".IFPSC02", 1);
NextTok ();
@ -470,6 +480,7 @@ int CheckConditionals (void)
case TOK_IFP4510:
case TOK_IFP816:
case TOK_IFPC02:
case TOK_IFPDTV:
case TOK_IFPSC02:
case TOK_IFREF:
DoConditionals ();

View File

@ -303,6 +303,91 @@ static const struct {
}
};
/* Instruction table for the 6502 with DTV extra opcodes (DTV) and
** those illegal instructions (X) which are supported by DTV.
** Note: illegals opcodes which contain more subinstructions
** (ASO, DCM, LSE, LXA, SBX and SHS) are not enlisted.
*/
static const struct {
unsigned Count;
InsDesc Ins[71];
} InsTab6502DTV = {
sizeof (InsTab6502DTV.Ins) / sizeof (InsTab6502DTV.Ins[0]),
{
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
{ "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */
{ "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */
{ "AND", 0x080A26C, 0x20, 0, PutAll },
{ "ANE", 0x0800000, 0x8B, 0, PutAll }, /* X */
{ "ARR", 0x0800000, 0x6B, 0, PutAll }, /* X */
{ "ASL", 0x000006e, 0x02, 1, PutAll },
{ "AXS", 0x0800000, 0xCB, 0, PutAll }, /* X */
{ "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
{ "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
{ "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
{ "BIT", 0x000000C, 0x00, 2, PutAll },
{ "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
{ "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
{ "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
{ "BRA", 0x0020000, 0x12, 0, PutPCRel8 }, /* DTV */
{ "BRK", 0x0000001, 0x00, 0, PutAll },
{ "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
{ "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
{ "CLC", 0x0000001, 0x18, 0, PutAll },
{ "CLD", 0x0000001, 0xd8, 0, PutAll },
{ "CLI", 0x0000001, 0x58, 0, PutAll },
{ "CLV", 0x0000001, 0xb8, 0, PutAll },
{ "CMP", 0x080A26C, 0xc0, 0, PutAll },
{ "CPX", 0x080000C, 0xe0, 1, PutAll },
{ "CPY", 0x080000C, 0xc0, 1, PutAll },
{ "DEC", 0x000006C, 0x00, 3, PutAll },
{ "DEX", 0x0000001, 0xca, 0, PutAll },
{ "DEY", 0x0000001, 0x88, 0, PutAll },
{ "EOR", 0x080A26C, 0x40, 0, PutAll },
{ "INC", 0x000006c, 0x00, 4, PutAll },
{ "INX", 0x0000001, 0xe8, 0, PutAll },
{ "INY", 0x0000001, 0xc8, 0, PutAll },
{ "JMP", 0x0000808, 0x4c, 6, PutJMP },
{ "JSR", 0x0000008, 0x20, 7, PutAll },
{ "LAS", 0x0000200, 0xBB, 0, PutAll }, /* X */
{ "LAX", 0x080A30C, 0xA3, 11, PutAll }, /* X */
{ "LDA", 0x080A26C, 0xa0, 0, PutAll },
{ "LDX", 0x080030C, 0xa2, 1, PutAll },
{ "LDY", 0x080006C, 0xa0, 1, PutAll },
{ "LSR", 0x000006F, 0x42, 1, PutAll },
{ "NOP", 0x080006D, 0x00, 10, PutAll }, /* X */
{ "ORA", 0x080A26C, 0x00, 0, PutAll },
{ "PHA", 0x0000001, 0x48, 0, PutAll },
{ "PHP", 0x0000001, 0x08, 0, PutAll },
{ "PLA", 0x0000001, 0x68, 0, PutAll },
{ "PLP", 0x0000001, 0x28, 0, PutAll },
{ "RLA", 0x000A26C, 0x23, 0, PutAll }, /* X */
{ "ROL", 0x000006F, 0x22, 1, PutAll },
{ "ROR", 0x000006F, 0x62, 1, PutAll },
{ "RRA", 0x000A26C, 0x63, 0, PutAll }, /* X */
{ "RTI", 0x0000001, 0x40, 0, PutAll },
{ "RTS", 0x0000001, 0x60, 0, PutAll },
{ "SAC", 0x0800000, 0x32, 1, PutAll }, /* DTV */
{ "SBC", 0x080A26C, 0xe0, 0, PutAll },
{ "SEC", 0x0000001, 0x38, 0, PutAll },
{ "SED", 0x0000001, 0xf8, 0, PutAll },
{ "SEI", 0x0000001, 0x78, 0, PutAll },
{ "SHA", 0x0002200, 0x93, 1, PutAll }, /* X */
{ "SHX", 0x0000200, 0x9e, 1, PutAll }, /* X */
{ "SHY", 0x0000040, 0x9c, 1, PutAll }, /* X */
{ "SIR", 0x0800000, 0x42, 1, PutAll }, /* DTV */
{ "STA", 0x000A26C, 0x80, 0, PutAll },
{ "STX", 0x000010c, 0x82, 1, PutAll },
{ "STY", 0x000002c, 0x80, 1, PutAll },
{ "TAX", 0x0000001, 0xaa, 0, PutAll },
{ "TAY", 0x0000001, 0xa8, 0, PutAll },
{ "TSX", 0x0000001, 0xba, 0, PutAll },
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll }
}
};
/* Instruction table for the 65SC02 */
static const struct {
unsigned Count;
@ -930,6 +1015,7 @@ static const InsTable* InsTabs[CPU_COUNT] = {
(const InsTable*) &InsTabNone,
(const InsTable*) &InsTab6502,
(const InsTable*) &InsTab6502X,
(const InsTable*) &InsTab6502DTV,
(const InsTable*) &InsTab65SC02,
(const InsTable*) &InsTab65C02,
(const InsTable*) &InsTab65816,

View File

@ -1552,6 +1552,14 @@ static void DoP4510 (void)
static void DoPDTV (void)
/* Switch to C64DTV CPU */
{
SetCPU (CPU_6502DTV);
}
static void DoPageLength (void)
/* Set the page length for the listing */
{
@ -2058,6 +2066,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccKeepToken, DoConditionals }, /* .IFP4510 */
{ ccKeepToken, DoConditionals }, /* .IFP816 */
{ ccKeepToken, DoConditionals }, /* .IFPC02 */
{ ccKeepToken, DoConditionals }, /* .IFPDTV */
{ ccKeepToken, DoConditionals }, /* .IFPSC02 */
{ ccKeepToken, DoConditionals }, /* .IFREF */
{ ccNone, DoImport },
@ -2091,6 +2100,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoPageLength },
{ ccNone, DoUnexpected }, /* .PARAMCOUNT */
{ ccNone, DoPC02 },
{ ccNone, DoPDTV },
{ ccNone, DoPopCPU },
{ ccNone, DoPopSeg },
{ ccNone, DoProc },

View File

@ -219,6 +219,7 @@ struct DotKeyword {
{ ".IFP4510", TOK_IFP4510 },
{ ".IFP816", TOK_IFP816 },
{ ".IFPC02", TOK_IFPC02 },
{ ".IFPDTV", TOK_IFPDTV },
{ ".IFPSC02", TOK_IFPSC02 },
{ ".IFREF", TOK_IFREF },
{ ".IMPORT", TOK_IMPORT },
@ -258,6 +259,7 @@ struct DotKeyword {
{ ".PAGELENGTH", TOK_PAGELENGTH },
{ ".PARAMCOUNT", TOK_PARAMCOUNT },
{ ".PC02", TOK_PC02 },
{ ".PDTV", TOK_PDTV },
{ ".POPCPU", TOK_POPCPU },
{ ".POPSEG", TOK_POPSEG },
{ ".PROC", TOK_PROC },

View File

@ -196,6 +196,7 @@ typedef enum token_t {
TOK_IFP4510,
TOK_IFP816,
TOK_IFPC02,
TOK_IFPDTV,
TOK_IFPSC02,
TOK_IFREF,
TOK_IMPORT,
@ -229,6 +230,7 @@ typedef enum token_t {
TOK_PAGELENGTH,
TOK_PARAMCOUNT,
TOK_PC02,
TOK_PDTV,
TOK_POPCPU,
TOK_POPSEG,
TOK_PROC,

View File

@ -186,6 +186,7 @@ void g_preamble (void)
switch (CPU) {
case CPU_6502: AddTextLine ("\t.setcpu\t\t\"6502\""); break;
case CPU_6502X: AddTextLine ("\t.setcpu\t\t\"6502X\""); break;
case CPU_6502DTV: AddTextLine ("\t.setcpu\t\t\"6502DTV\""); break;
case CPU_65SC02: AddTextLine ("\t.setcpu\t\t\"65SC02\""); break;
case CPU_65C02: AddTextLine ("\t.setcpu\t\t\"65C02\""); break;
case CPU_65816: AddTextLine ("\t.setcpu\t\t\"65816\""); break;
@ -1432,6 +1433,22 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs)
/* Note that this logic is largely duplicated by ArithmeticConvert. */
/* Before we apply the integral promotions, we check if both types are the same character type.
** If so, we return that type, rather than int, which would be returned by the standard
** rules. This is only a performance optimization allowing the use of unsigned and/or char
** operations; it does not affect correctness, as the flags are only used for code generation,
** and not to determine types of other expressions containing this one. For codgen, CF_CHAR
** means the operands are char and the result is int (unless CF_FORCECHAR is also set, in
** which case the result is char). This special case part is not duplicated by
** ArithmeticConvert.
*/
if ((lhs & CF_TYPEMASK) == CF_CHAR && (rhs & CF_TYPEMASK) == CF_CHAR &&
(lhs & CF_UNSIGNED) == (rhs & CF_UNSIGNED)) {
/* Signedness flags are the same, so just use one of them. */
const unsigned unsigned_flag = lhs & CF_UNSIGNED;
return const_flag | unsigned_flag | CF_CHAR;
}
/* Apply integral promotions for types char/short. */
lhs = g_intpromotion (lhs);
rhs = g_intpromotion (rhs);
@ -2461,7 +2478,7 @@ void g_branch (unsigned Label)
** the label cannot be farther away from the branch than -128/+127 bytes.
*/
{
if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0) {
if ((CPUIsets[CPU] & (CPU_ISET_65SC02 | CPU_ISET_6502DTV)) != 0) {
AddCodeLine ("bra %s", LocalLabelName (Label));
} else {
g_jump (Label);
@ -3090,18 +3107,33 @@ void g_asr (unsigned flags, unsigned long val)
"tosasrax", "tosshrax", "tosasreax", "tosshreax"
};
/* If the right hand side is const, the lhs is not on stack but still
/* If the right hand side is const, the lhs is not on stack, but still
** in the primary register.
*/
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
case CF_CHAR:
if (flags & CF_FORCECHAR) {
if ((flags & CF_UNSIGNED) != 0 && val <= 4) {
val &= 7;
if ((flags & CF_UNSIGNED) != 0) {
/* Instead of `val` right shifts, we can also do `9 - val` left rotates
** and a mask. This saves 3 bytes and 8 cycles for `val == 7` and
** 1 byte and 4 cycles for `val == 6`.
*/
if (val < 6) {
while (val--) {
AddCodeLine ("lsr a");
AddCodeLine ("lsr a"); /* 1 byte, 2 cycles */
}
} else {
unsigned i;
/* The first ROL shifts in garbage and sets carry to the high bit.
** The garbage is cleaned up by the mask.
*/
for (i = val; i < 9; ++i) {
AddCodeLine ("rol a"); /* 1 byte, 2 cycles */
}
/* 2 bytes, 2 cycles */
AddCodeLine ("and #$%02X", 0xFF >> val);
}
return;
} else if (val <= 2) {
@ -3111,19 +3143,28 @@ void g_asr (unsigned flags, unsigned long val)
}
return;
}
AddCodeLine ("ldx #$00");
if ((flags & CF_UNSIGNED) == 0) {
unsigned L = GetLocalLabel ();
AddCodeLine ("cmp #$80"); /* Sign bit into carry */
AddCodeLine ("bcc %s", LocalLabelName (L));
AddCodeLine ("dex"); /* Make $FF */
g_defcodelabel (L);
}
}
/* FALLTHROUGH */
case CF_INT:
val &= 0x0F;
if (val >= 8) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("txa");
if (flags & CF_UNSIGNED) {
AddCodeLine ("ldx #$00");
} else {
unsigned L = GetLocalLabel ();
AddCodeLine ("cpx #$80"); /* Sign bit into carry */
AddCodeLine ("txa");
AddCodeLine ("ldx #$00");
AddCodeLine ("bcc %s", LocalLabelName (L));
AddCodeLine ("dex"); /* Make $FF */
@ -3141,9 +3182,9 @@ void g_asr (unsigned flags, unsigned long val)
}
if (val > 0) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr shrax%ld", val);
AddCodeLine ("jsr shrax%lu", val);
} else {
AddCodeLine ("jsr asrax%ld", val);
AddCodeLine ("jsr asrax%lu", val);
}
}
return;
@ -3155,6 +3196,7 @@ void g_asr (unsigned flags, unsigned long val)
AddCodeLine ("lda sreg+1");
if ((flags & CF_UNSIGNED) == 0) {
unsigned L = GetLocalLabel ();
AddCodeLine ("bpl %s", LocalLabelName (L));
AddCodeLine ("dex");
g_defcodelabel (L);
@ -3168,6 +3210,7 @@ void g_asr (unsigned flags, unsigned long val)
AddCodeLine ("ldx sreg+1");
if ((flags & CF_UNSIGNED) == 0) {
unsigned L = GetLocalLabel ();
AddCodeLine ("bpl %s", LocalLabelName (L));
AddCodeLine ("dey");
g_defcodelabel (L);
@ -3184,6 +3227,7 @@ void g_asr (unsigned flags, unsigned long val)
AddCodeLine ("sty sreg");
if ((flags & CF_UNSIGNED) == 0) {
unsigned L = GetLocalLabel ();
AddCodeLine ("cpy #$80");
AddCodeLine ("ldy #$00");
AddCodeLine ("bcc %s", LocalLabelName (L));
@ -3205,9 +3249,9 @@ void g_asr (unsigned flags, unsigned long val)
}
if (val > 0) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr shreax%ld", val);
AddCodeLine ("jsr shreax%lu", val);
} else {
AddCodeLine ("jsr asreax%ld", val);
AddCodeLine ("jsr asreax%lu", val);
}
}
return;
@ -3237,18 +3281,28 @@ void g_asl (unsigned flags, unsigned long val)
"tosaslax", "tosshlax", "tosasleax", "tosshleax"
};
/* If the right hand side is const, the lhs is not on stack but still
/* If the right hand side is const, the lhs is not on stack, but still
** in the primary register.
*/
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
case CF_CHAR:
if ((flags & CF_FORCECHAR) != 0 && val <= 4) {
if ((flags & CF_FORCECHAR) != 0) {
val &= 7;
/* Large shifts are faster and smaller with ROR. See g_asr for detailed
** byte and cycle counts.
*/
if (val < 6) {
while (val--) {
AddCodeLine ("asl a");
}
} else {
unsigned i;
for (i = val; i < 9; ++i) {
AddCodeLine ("ror a");
}
AddCodeLine ("and #$%02X", (~0U << val) & 0xFF);
}
return;
}
/* FALLTHROUGH */
@ -3270,9 +3324,9 @@ void g_asl (unsigned flags, unsigned long val)
}
if (val > 0) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr shlax%ld", val);
AddCodeLine ("jsr shlax%lu", val);
} else {
AddCodeLine ("jsr aslax%ld", val);
AddCodeLine ("jsr aslax%lu", val);
}
}
return;
@ -3311,9 +3365,9 @@ void g_asl (unsigned flags, unsigned long val)
}
if (val > 0) {
if (flags & CF_UNSIGNED) {
AddCodeLine ("jsr shleax%ld", val);
AddCodeLine ("jsr shleax%lu", val);
} else {
AddCodeLine ("jsr asleax%ld", val);
AddCodeLine ("jsr asleax%lu", val);
}
}
return;

View File

@ -493,13 +493,16 @@ fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg)
** registers.
*/
*Use = REG_EAXY;
} else if (D->ParamCount > 0 &&
} else if ((D->ParamCount > 0 ||
(D->Flags & FD_EMPTY) != 0) &&
(AutoCDecl ?
IsQualFastcall (E->Type) :
!IsQualCDecl (E->Type))) {
/* Will use registers depending on the last param. If the last
** param has incomplete type, just assume __EAX__.
** param has incomplete type, or if the function has not been
** prototyped yet, just assume __EAX__.
*/
if (D->LastParam != 0) {
switch (SizeOf(D->LastParam->Type)) {
case 1u:
*Use = REG_A;
@ -510,6 +513,9 @@ fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg)
default:
*Use = REG_EAX;
}
} else {
*Use = REG_EAX;
}
} else {
/* Will not use any registers */
*Use = REG_NONE;

View File

@ -1080,7 +1080,7 @@ void AddOpHigh (StackOpData* D, opc_t OPC, LoadInfo* LI, int KeepResult)
} else {
if ((LI->A.Flags & LI_CHECK_Y) == 0) {
if ((LI->X.Flags & LI_CHECK_Y) == 0) {
/* ldy #const */
X = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (LI->X.Offs), 0, D->OpEntry->LI);
} else {
@ -1094,7 +1094,7 @@ void AddOpHigh (StackOpData* D, opc_t OPC, LoadInfo* LI, int KeepResult)
X = NewCodeEntry (OPC, AM65_ZP_INDY, "sp", 0, D->OpEntry->LI);
} else {
/* opc src,y */
X = NewCodeEntry (OPC, LI->A.LoadEntry->AM, LI->A.LoadEntry->Arg, 0, D->OpEntry->LI);
X = NewCodeEntry (OPC, LI->X.LoadEntry->AM, LI->X.LoadEntry->Arg, 0, D->OpEntry->LI);
}
InsertEntry (D, X, D->IP++);
}

View File

@ -944,7 +944,9 @@ unsigned OptCmp9 (CodeSeg* S)
if (L[0]->OPC == OP65_SBC &&
CS_GetEntries (S, L+1, I+1, 4) &&
(L[1]->OPC == OP65_BVC ||
L[1]->OPC == OP65_BVS) &&
L[1]->OPC == OP65_BVS ||
L[1]->OPC == OP65_JVC ||
L[1]->OPC == OP65_JVS) &&
L[1]->JumpTo != 0 &&
L[1]->JumpTo->Owner == L[3] &&
L[2]->OPC == OP65_EOR &&

View File

@ -173,7 +173,7 @@ unsigned OptBranchDist (CodeSeg* S)
}
} else if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 &&
} else if ((CPUIsets[CPU] & (CPU_ISET_65SC02 |CPU_ISET_6502DTV)) != 0 &&
(E->Info & OF_UBRA) != 0 &&
E->JumpTo != 0 &&
IsShortDist (GetBranchDist (S, I, E->JumpTo->Owner))) {

View File

@ -988,7 +988,7 @@ unsigned OptPtrLoad12 (CodeSeg* S)
L[4]->OPC == OP65_CLC &&
L[5]->OPC == OP65_ADC &&
CE_IsKnownImm (L[5], 1) &&
L[6]->OPC == OP65_BCC &&
(L[6]->OPC == OP65_BCC || L[6]->OPC == OP65_JCC) &&
L[6]->JumpTo != 0 &&
L[6]->JumpTo->Owner == L[8] &&
L[7]->OPC == OP65_INX &&

View File

@ -341,7 +341,10 @@ unsigned OptShift2 (CodeSeg* S)
L[0] = CS_GetEntry (S, I);
/* Check for the sequence */
if ((L[0]->OPC == OP65_BPL || L[0]->OPC == OP65_BCC) &&
if ((L[0]->OPC == OP65_BPL ||
L[0]->OPC == OP65_BCC ||
L[0]->OPC == OP65_JPL ||
L[0]->OPC == OP65_JCC) &&
L[0]->JumpTo != 0 &&
CS_GetEntries (S, L+1, I+1, 3) &&
L[1]->OPC == OP65_DEX &&

View File

@ -453,6 +453,7 @@ static unsigned Opt_staxspidx (StackOpData* D)
/* Optimize the staxspidx sequence */
{
CodeEntry* X;
const char* Arg = 0;
/* Check if we're using a register variable */
if (!IsRegVar (D)) {
@ -469,7 +470,7 @@ static unsigned Opt_staxspidx (StackOpData* D)
if (RegValIsKnown (D->OpEntry->RI->In.RegY)) {
/* Value of Y is known */
const char* Arg = MakeHexArg (D->OpEntry->RI->In.RegY + 1);
Arg = MakeHexArg (D->OpEntry->RI->In.RegY + 1);
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, D->OpEntry->LI);
} else {
X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, D->OpEntry->LI);
@ -478,7 +479,7 @@ static unsigned Opt_staxspidx (StackOpData* D)
if (RegValIsKnown (D->OpEntry->RI->In.RegX)) {
/* Value of X is known */
const char* Arg = MakeHexArg (D->OpEntry->RI->In.RegX);
Arg = MakeHexArg (D->OpEntry->RI->In.RegX);
X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, D->OpEntry->LI);
} else {
/* Value unknown */
@ -493,7 +494,12 @@ static unsigned Opt_staxspidx (StackOpData* D)
/* If we remove staxspidx, we must restore the Y register to what the
** function would return.
*/
X = NewCodeEntry (OP65_LDY, AM65_IMM, "$00", 0, D->OpEntry->LI);
if (RegValIsKnown (D->OpEntry->RI->In.RegY)) {
Arg = MakeHexArg (D->OpEntry->RI->In.RegY);
X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, D->OpEntry->LI);
} else {
X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, D->OpEntry->LI);
}
InsertEntry (D, X, D->OpIndex+5);
/* Remove the push and the call to the staxspidx function */
@ -1100,7 +1106,7 @@ static unsigned Opt_tosxorax (StackOpData* D)
static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
/* Optimize the tos compare sequence with a bool transformer */
/* Optimize the TOS compare sequence with a bool transformer */
{
CodeEntry* X;
cmp_t Cond;
@ -1119,9 +1125,8 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
D->Rhs.A.Flags |= LI_REMOVE;
} else if ((D->Lhs.A.Flags & LI_DIRECT) != 0) {
/* If the lhs is direct (but not stack relative), encode compares with lhs
** effectively reverting the order (which doesn't matter for ==).
/* If the lhs is direct (but not stack relative), encode compares with lhs,
** effectively reversing the order (which doesn't matter for == and !=).
*/
Cond = FindBoolCmpCond (BoolTransformer);
Cond = GetRevertedCond (Cond);
@ -1138,7 +1143,6 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
D->Lhs.A.Flags |= LI_REMOVE;
} else {
/* We'll do reverse-compare */
Cond = FindBoolCmpCond (BoolTransformer);
Cond = GetRevertedCond (Cond);
@ -1162,7 +1166,7 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
X = NewCodeEntry (OP65_JSR, AM65_ABS, BoolTransformer, 0, D->OpEntry->LI);
InsertEntry (D, X, D->IP++);
/* Remove the push and the call to the tosgeax function */
/* Remove the push and the call to the TOS function */
RemoveRemainders (D);
/* We changed the sequence */
@ -1179,22 +1183,6 @@ static unsigned Opt_a_toseq (StackOpData* D)
static unsigned Opt_a_tosge (StackOpData* D)
/* Optimize the tosgeax sequence */
{
return Opt_a_toscmpbool (D, "boolge");
}
static unsigned Opt_a_tosgt (StackOpData* D)
/* Optimize the tosgtax sequence */
{
return Opt_a_toscmpbool (D, "boolgt");
}
static unsigned Opt_a_tosicmp (StackOpData* D)
/* Replace tosicmp with CMP */
{
@ -1268,15 +1256,15 @@ static unsigned Opt_a_tosicmp (StackOpData* D)
InsertEntry (D, X, D->IP-3);
} else {
/* Just clear A,Z,N and set C */
/* Just clear A,Z,N; and set C */
Arg = MakeHexArg (0);
if ((RI = GetLastChangedRegInfo (D, &D->Lhs.A)) != 0 &&
RegValIsKnown (RI->Out.RegA) &&
(RI->Out.RegA & 0xFF) == 0) {
Arg = MakeHexArg (0);
X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI);
InsertEntry (D, X, D->OpIndex + 1);
} else {
Arg = MakeHexArg (0);
X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, D->OpEntry->LI);
InsertEntry (D, X, D->OpIndex + 1);
X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI);
@ -1292,24 +1280,8 @@ static unsigned Opt_a_tosicmp (StackOpData* D)
static unsigned Opt_a_tosle (StackOpData* D)
/* Optimize the tosleax sequence */
{
return Opt_a_toscmpbool (D, "boolle");
}
static unsigned Opt_a_toslt (StackOpData* D)
/* Optimize the tosltax sequence */
{
return Opt_a_toscmpbool (D, "boollt");
}
static unsigned Opt_a_tosne (StackOpData* D)
/* Optimize the toseqax sequence */
/* Optimize the tosneax sequence */
{
return Opt_a_toscmpbool (D, "boolne");
}
@ -1317,7 +1289,7 @@ static unsigned Opt_a_tosne (StackOpData* D)
static unsigned Opt_a_tosuge (StackOpData* D)
/* Optimize the tosugeax sequence */
/* Optimize the tosgeax and tosugeax sequences */
{
return Opt_a_toscmpbool (D, "booluge");
}
@ -1325,7 +1297,7 @@ static unsigned Opt_a_tosuge (StackOpData* D)
static unsigned Opt_a_tosugt (StackOpData* D)
/* Optimize the tosugtax sequence */
/* Optimize the tosgtax and tosugtax sequences */
{
return Opt_a_toscmpbool (D, "boolugt");
}
@ -1333,7 +1305,7 @@ static unsigned Opt_a_tosugt (StackOpData* D)
static unsigned Opt_a_tosule (StackOpData* D)
/* Optimize the tosuleax sequence */
/* Optimize the tosleax and tosuleax sequences */
{
return Opt_a_toscmpbool (D, "boolule");
}
@ -1341,7 +1313,7 @@ static unsigned Opt_a_tosule (StackOpData* D)
static unsigned Opt_a_tosult (StackOpData* D)
/* Optimize the tosultax sequence */
/* Optimize the tosltax and tosultax sequences */
{
return Opt_a_toscmpbool (D, "boolult");
}
@ -1354,6 +1326,8 @@ static unsigned Opt_a_tosult (StackOpData* D)
/* The first column of these two tables must be sorted in lexical order */
static const OptFuncDesc FuncTable[] = {
{ "__bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN },
{ "staspidx", Opt_staspidx, REG_NONE, OP_NONE },
@ -1379,11 +1353,11 @@ static const OptFuncDesc FuncTable[] = {
static const OptFuncDesc FuncRegATable[] = {
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
{ "tosgeax", Opt_a_tosge, REG_NONE, OP_NONE },
{ "tosgtax", Opt_a_tosgt, REG_NONE, OP_NONE },
{ "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE },
{ "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE },
{ "tosicmp", Opt_a_tosicmp, REG_NONE, OP_NONE },
{ "tosleax", Opt_a_tosle, REG_NONE, OP_NONE },
{ "tosltax", Opt_a_toslt, REG_NONE, OP_NONE },
{ "tosleax", Opt_a_tosule, REG_NONE, OP_NONE },
{ "tosltax", Opt_a_tosult, REG_NONE, OP_NONE },
{ "tosneax", Opt_a_tosne, REG_NONE, OP_NONE },
{ "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE },
{ "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE },
@ -1732,7 +1706,7 @@ unsigned OptStackOps (CodeSeg* S)
int I;
int OldEntryCount; /* Old number of entries */
unsigned Used; /* What registers would be used */
unsigned PushedRegs; /* Track if the same regs are used after the push */
unsigned PushedRegs = 0; /* Track if the same regs are used after the push */
int RhsAChgIndex; /* Track if rhs is changed more than once */
int RhsXChgIndex; /* Track if rhs is changed more than once */
int IsRegAOptFunc = 0; /* Whether to use the RegA-only optimizations */

Some files were not shown because too many files have changed in this diff Show More