/bin/
-/emd/
/html/
/info/
-/joy/
/lib/
/libwrk/
-/mou/
-/ser/
-/targetutil/
+/target/
/testwrk/
-/tgi/
/wrk/
+/cc65.zip
-.PHONY: all mostlyclean clean install zip avail unavail bin lib doc
+.PHONY: all mostlyclean clean install zip avail unavail bin lib doc samples
.SUFFIXES:
all mostlyclean clean install zip:
- @$(MAKE) -C src --no-print-directory $@
- @$(MAKE) -C libsrc --no-print-directory $@
- @$(MAKE) -C doc --no-print-directory $@
+ @$(MAKE) -C src --no-print-directory $@
+ @$(MAKE) -C libsrc --no-print-directory $@
+ @$(MAKE) -C doc --no-print-directory $@
+ @$(MAKE) -C samples --no-print-directory $@
avail unavail bin:
- @$(MAKE) -C src --no-print-directory $@
+ @$(MAKE) -C src --no-print-directory $@
lib:
- @$(MAKE) -C libsrc --no-print-directory $@
+ @$(MAKE) -C libsrc --no-print-directory $@
doc:
- @$(MAKE) -C doc --no-print-directory $@
+ @$(MAKE) -C doc --no-print-directory $@
+
+samples:
+ @$(MAKE) -C samples --no-print-directory $@
%65:
- @$(MAKE) -C src --no-print-directory $@
+ @$(MAKE) -C src --no-print-directory $@
%:
- @$(MAKE) -C libsrc --no-print-directory $@
+ @$(MAKE) -C libsrc --no-print-directory $@
--- /dev/null
+; Convert characters to screen codes
+
+; Helper macro that converts and outputs one character
+.macro _scrcode char
+ .if (char < 256)
+ .byte (char + 128)
+ .else
+ .error "scrcode: Character constant out of range"
+ .endif
+.endmacro
+
+.macro scrcode arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
+
+ ; Bail out if next argument is empty
+ .if .blank (arg1)
+ .exitmacro
+ .endif
+
+ ; Check for a string
+ .if .match ({arg1}, "")
+
+ ; Walk over all string chars
+ .repeat .strlen (arg1), i
+ _scrcode {.strat (arg1, i)}
+ .endrepeat
+
+ ; Check for a number
+ .elseif .match (.left (1, {arg1}), 0)
+
+ ; Just output the number
+ _scrcode arg1
+
+ ; Check for a character
+ .elseif .match (.left (1, {arg1}), 'a')
+
+ ; Just output the character
+ _scrcode arg1
+
+ ; Anything else is an error
+ .else
+
+ .error "scrcode: invalid argument type"
+
+ .endif
+
+ ; Call the macro recursively with the remaining args
+ scrcode arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
+.endmacro
SIO_WRITE = $50 ;write sector
SIO_READ = $52 ;read sector
SIO_STAT = $53 ;get status information
-SIO_VERIFY = $56 ;verify sector
+SIO_VERIFY = $56 ;verify sector
SIO_WRITEV = $57 ;write sector with verify
SIO_WRITETRK = $60 ;write track (Speedy)
SIO_READTRK = $62 ;read track (Speedy)
PNTINV = 171 ;($AB) point invalid
BADDSK = 173 ;($AD) bad disk
INCFMT = 176 ;($B0) DOS 3: incompatible file system
+XNTBIN = 180 ;($B4) XDOS: file not binary
; DCB Device Bus Equates
TIMER2 = $0310 ;2-byte final baud rate timer value
TEMP1 = $0312 ;TEMPORARY STORAGE REGISTER
;TEMP2 = $0314 ;##old## TEMPORARY STORAGE REGISTER
-TEMP2 = $0313 ;##1200xl## 1-byte temporary
+TEMP2 = $0313 ;##1200xl## 1-byte temporary
PTIMOT = $0314 ;##1200xl## 1-byte printer timeout
TEMP3 = $0315 ;TEMPORARY STORAGE REGISTER
SAVIO = $0316 ;SAVE SERIAL IN DATA PORT
;0=Cart Exists
CARTFG = $BFFD ;##rev2## 1-byte cartridge flags
;D7 0=Not a Diagnostic Cart
- ; 1=Is a Diagnostic cart and control is
+ ; 1=Is a Diagnostic cart and control is
; given to cart before any OS is init.
;D2 0=Init but Do not Start Cart
; 1=Init and Start Cart
CIOV = $E456 ;vector to CIO
SIOV = $E459 ;vector to SIO
SETVBV = $E45C ;vector to set VBLANK parameters
+; aliases in order not to have to sprinkle common code with .ifdefs
+CIOV_org = CIOV
+SIOV_org = SIOV
+SETVBV_org = SETVBV
.endif
SYSVBV = $E45F ;vector to process immediate VBLANK
XITVBV = $E462 ;vector to process deferred VBLANK
DEGON = 6 ;INDICATES DEGREES
ASCZER = '0' ;ASCII ZERO
-COLON = $3A ;ASCII COLON
+COLON = $3A ;ASCII COLON
CR = $9B ;SYSTEM EOL (CARRIAGE RETURN)
;-------------------------------------------------------------------------
; VALUES for dos_type
;-------------------------------------------------------------------------
-ATARIDOS = 0
-SPARTADOS = 1
-OSADOS = 2 ; OS/A+
-MYDOS = 3
-XDOS = 4
+SPARTADOS = 0
+OSADOS = 1 ; OS/A+
+XDOS = 2
+ATARIDOS = 3
+MYDOS = 4
NODOS = 255
+; The DOSes with dos_type below or equal MAX_DOS_WITH_CMDLINE do support
+; command line arguments.
+MAX_DOS_WITH_CMDLINE = XDOS
+
+;-------------------------------------------------------------------------
+; XDOS defines (version 2.4, taken from xdos24.pdf)
+;-------------------------------------------------------------------------
+
+XOPT = $070B ; XDOS options
+XCAR = $070C ; XDOS cartridge address (+ $70D)
+XPAT = $086F ; XDOS bugfix and patch number
+XVER = $0870 ; XDOS version number
+XFILE = $087D ; XDOS filename buffer
+XLINE = $0880 ; XDOS DUP input line
+XGLIN = $0871 ; get line
+XSKIP = $0874 ; skip parameter
+.ifdef __ATARIXL__
+.ifndef SHRAM_HANDLERS
+.import XMOVE_handler
+.endif
+.define XMOVE XMOVE_handler
+XMOVE_org = $0877 ; move filename
+.else
+XMOVE = $0877 ; move filename
+.endif
+XGNUM = $087A ; get number
;-------------------------------------------------------------------------
; End of atari.inc
--- /dev/null
+; Atari 2600 TIA & RIOT read / write registers
+;
+; Florent Flament (contact@florentflament.com), 2017
+
+; TIA & RIOT registers mapping
+.include "atari2600_tia.inc"
+.include "atari2600_riot.inc"
--- /dev/null
+; Atari 2600 RIOT read / write registers
+;
+; Source: DASM - vcs.h
+; Details available in: Stella Programmer's Guide by Steve Wright
+;
+; Florent Flament (contact@florentflament.com), 2017
+
+; Read registers
+SWCHA := $0280
+SWACNT := $0281
+SWCHB := $0282
+SWBCNT := $0283
+INTIM := $0284
+TIMINT := $0285
+
+; Write registers
+TIM1T := $0294
+TIM8T := $0295
+TIM64T := $0296
+T1024T := $0297
--- /dev/null
+; Atari 2600 TIA read / write registers
+;
+; Source: DASM - vcs.h
+; Details available in: Stella Programmer's Guide by Steve Wright
+;
+; Florent Flament (contact@florentflament.com), 2017
+
+; Read registers
+VSYNC := $00
+VBLANK := $01
+WSYNC := $02
+RSYNC := $03
+NUSIZ0 := $04
+NUSIZ1 := $05
+COLUP0 := $06
+COLUP1 := $07
+COLUPF := $08
+COLUBK := $09
+CTRLPF := $0A
+REFP0 := $0B
+REFP1 := $0C
+PF0 := $0D
+PF1 := $0E
+PF2 := $0F
+RESP0 := $10
+RESP1 := $11
+RESM0 := $12
+RESM1 := $13
+RESBL := $14
+AUDC0 := $15
+AUDC1 := $16
+AUDF0 := $17
+AUDF1 := $18
+AUDV0 := $19
+AUDV1 := $1A
+GRP0 := $1B
+GRP1 := $1C
+ENAM0 := $1D
+ENAM1 := $1E
+ENABL := $1F
+HMP0 := $20
+HMP1 := $21
+HMM0 := $22
+HMM1 := $23
+HMBL := $24
+VDELP0 := $25
+VDELP1 := $26
+VDELBL := $27
+RESMP0 := $28
+RESMP1 := $29
+HMOVE := $2A
+HMCLR := $2B
+CXCLR := $2C
+
+; Write registers
+CXM0P := $00
+CXM1P := $01
+CXP0FB := $02
+CXP1FB := $03
+CXM0FB := $04
+CXM1FB := $05
+CXBLPF := $06
+CXPPMM := $07
+INPT0 := $08
+INPT1 := $09
+INPT2 := $0A
+INPT3 := $0B
+INPT4 := $0C
+INPT5 := $0D
CPU_ISET_65816 = $0020
CPU_ISET_SWEET16 = $0040
CPU_ISET_HUC6280 = $0080
+;CPU_ISET_M740 = $0100 not actually implemented
+CPU_ISET_4510 = $0200
; CPU capabilities
CPU_NONE = CPU_ISET_NONE
CPU_65816 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65816
CPU_SWEET16 = CPU_ISET_SWEET16
CPU_HUC6280 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02|CPU_ISET_HUC6280
+CPU_4510 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02|CPU_ISET_4510
ESPIPE ; Illegal seek
ERANGE ; Range error
EBADF ; Bad file number
+ ENOEXEC ; Exec format error
EUNKNOWN ; Unknown OS specific error - must be last!
EMAX = EUNKNOWN ; Highest error code
;
; Reference:
; Bastian Schick's Lynx Documentation
-; http://www.geocities.com/SiliconValley/Byte/4242/lynx/
+; http://www.geocities.ws/SiliconValley/Byte/4242/lynx/
;
; ***
; smc.mac\r
; ca65 Macro-Pack for Self Modifying Code (SMC)\r
;\r
-; (c) Christian Krüger, latest change: 09-Nov-2011\r
+; (c) Christian Krüger, latest change: 17-Jul-2016\r
;\r
; This software is provided 'as-is', without any expressed or implied\r
; warranty. In no event will the authors be held liable for any damages\r
.endmacro\r
\r
.macro SMC_TransferOpcode label, opcode, register\r
-.if .paramcount = 2 .or .match ({register}, a)\r
+.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
lda #opcode\r
sta _SMCDesignator\r
.elseif .match ({register}, x)\r
.elseif .match ({register}, y)\r
ldy #opcode\r
sty _SMCDesignator\r
+.else\r
+ .error "Invalid usage of macro 'SMC_TransferOpcode'"\r
.endif\r
.endmacro\r
\r
.macro SMC_LoadOpcode label, register\r
-.if .paramcount = 1 .or .match ({register}, a)\r
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
lda _SMCDesignator\r
.elseif .match ({register}, x)\r
ldx _SMCDesignator\r
.elseif .match ({register}, y)\r
ldy _SMCDesignator\r
+.else\r
+ .error "Invalid usage of macro 'SMC_LoadOpcode'"\r
.endif\r
.endmacro\r
\r
.macro SMC_StoreOpcode label, register\r
-.if .paramcount = 1 .or .match ({register}, a)\r
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
sta _SMCDesignator\r
.elseif .match ({register}, x)\r
stx _SMCDesignator\r
.elseif .match ({register}, y)\r
sty _SMCDesignator\r
+.else\r
+ .error "Invalid usage of macro 'SMC_StoreOpcode'"\r
.endif\r
.endmacro\r
\r
.macro SMC_ChangeBranch label, destination, register\r
-.if .paramcount = 2 .or .match ({register}, a)\r
- lda #(destination - _SMCDesignator -2)\r
+.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
+ lda #(<(destination - _SMCDesignator -2))\r
sta _SMCDesignator+1\r
.elseif .match ({register}, x)\r
- ldx #(destination - _SMCDesignator - 2)\r
+ ldx #(<(destination - _SMCDesignator - 2))\r
stx _SMCDesignator+1\r
.elseif .match ({register}, y)\r
- ldy #(destination - _SMCDesignator - 2)\r
+ ldy #(<(destination - _SMCDesignator - 2))\r
sty _SMCDesignator+1\r
+.else\r
+ .error "Invalid usage of macro 'SMC_ChangeBranch'"\r
.endif\r
.endmacro\r
\r
.macro SMC_TransferValue label, value, register\r
-.if .paramcount = 2 .or .match ({register}, a)\r
+.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
lda value\r
sta _SMCDesignator+1\r
.elseif .match ({register}, x)\r
.elseif .match ({register}, y)\r
ldy value\r
sty _SMCDesignator+1\r
+.else\r
+ .error "Invalid usage of macro 'SMC_TransferValue'"\r
.endif\r
.endmacro\r
\r
.macro SMC_LoadValue label, register\r
-.if .paramcount = 1 .or .match ({register}, a)\r
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
lda _SMCDesignator+1\r
.elseif .match ({register}, x)\r
ldx _SMCDesignator+1\r
.elseif .match ({register}, y)\r
ldy _SMCDesignator+1\r
+.else\r
+ .error "Invalid usage of macro 'SMC_LoadValue'"\r
.endif\r
.endmacro\r
\r
.macro SMC_StoreValue label, register\r
-.if .paramcount = 1 .or .match ({register}, a)\r
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
sta _SMCDesignator+1\r
.elseif .match ({register}, x)\r
stx _SMCDesignator+1\r
.elseif .match ({register}, y)\r
sty _SMCDesignator+1\r
+.else\r
+ .error "Invalid usage of macro 'SMC_StoreValue'"\r
.endif\r
.endmacro\r
\r
.endmacro\r
\r
.macro SMC_TransferHighByte label, value, register\r
-.if .paramcount = 2 .or .match ({register}, a)\r
+.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
lda value\r
sta _SMCDesignator+2\r
.elseif .match ({register}, x)\r
.elseif .match ({register}, y)\r
ldy value\r
sty _SMCDesignator+2\r
+.else\r
+ .error "Invalid usage of macro 'SMC_TransferHighByte'"\r
.endif\r
.endmacro\r
\r
.macro SMC_LoadHighByte label, register\r
-.if .paramcount = 1 .or .match ({register}, a)\r
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
lda _SMCDesignator+2\r
.elseif .match ({register}, x)\r
ldx _SMCDesignator+2\r
.elseif .match ({register}, y)\r
ldy _SMCDesignator+2\r
+.else\r
+ .error "Invalid usage of macro 'SMC_LoadHighByte'"\r
.endif\r
.endmacro\r
\r
.macro SMC_StoreHighByte label, register\r
-.if .paramcount = 1 .or .match ({register}, a)\r
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
sta _SMCDesignator+2\r
.elseif .match ({register}, x)\r
stx _SMCDesignator+2\r
.elseif .match ({register}, y)\r
sty _SMCDesignator+2\r
+.else\r
+ .error "Invalid usage of macro 'SMC_StoreHighByte'"\r
.endif\r
.endmacro\r
\r
.macro SMC_TransferAddressSingle label, address, register\r
-.if .paramcount = 2 .or .match ((register), a)\r
+.if .paramcount = 2 .or .match ((register), a) .or .match ({register}, )\r
.if (.match (.left (1, {address}), #))\r
; immediate mode\r
lda #<(.right (.tcount ({address})-1, {address}))\r
ldy 1+(address)\r
sty _SMCDesignator+2\r
.endif\r
+.else\r
+ .error "Invalid usage of macro 'SMC_TransferAddressSingle'"\r
.endif\r
.endmacro\r
\r
; supervision symbols
-; supervision 65c02s
-; in cc65 up to 2.9.1 65c02 means 65c02s
-.pc02
+; supervision 65c02s
+; in cc65 up to 2.9.1 65c02 means 65sc02
lcd_addr = $4000
LCD_LINESIZE = $30
FEATURES {
STARTADDRESS: default = $0803;
}
-SYMBOLS {
- __LOADADDR__: type = weak, value = __CODE_RUN__;
- __LOADSIZE__: type = weak, value = __BSS_RUN__ - __CODE_RUN__;
-}
MEMORY {
- ZP: start = $0080, size = $001A, define = yes;
- HEADER: file = %O, start = $0000, size = $0004;
- RAM: file = %O, start = %S, size = $C000 - %S;
+ ZP: file = "", start = $0000, size = $00FF;
+ HEADER: file = %O, start = %S - 4, size = $0004;
+ MAIN: file = %O, define = yes, start = %S, size = $C000 - %S;
+ BSS: file = "", start = __MAIN_LAST__, size = $C000 - __MAIN_LAST__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
EXEHDR: load = HEADER, type = ro, optional = yes;
- CODE: load = RAM, type = rw, optional = yes, define = yes;
- RODATA: load = RAM, type = ro, optional = yes;
- DATA: load = RAM, type = rw, optional = yes;
- BSS: load = RAM, type = bss, optional = yes, define = yes;
+ CODE: load = MAIN, type = rw;
+ RODATA: load = MAIN, type = ro, optional = yes;
+ DATA: load = MAIN, type = rw, optional = yes;
+ BSS: load = BSS, type = bss, optional = yes, define = yes;
}
}
SYMBOLS {
__EXEHDR__: type = import;
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
__HIMEM__: type = weak, value = $9600; # Presumed RAM end
__LCADDR__: type = weak, value = $D400; # Behind quit code
__LCSIZE__: type = weak, value = $0C00; # Rest of bank two
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
__OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay
- __LOADADDR__: type = weak, value = __STARTUP_RUN__;
- __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ +
- __MOVE_LAST__ - __MOVE_START__;
}
MEMORY {
- ZP: define = yes, start = $0080, size = $001A;
- HEADER: file = %O, start = $0000, size = $0004;
- RAM: file = %O, start = %S + __OVERLAYSIZE__, size = __HIMEM__ - __STACKSIZE__ - __OVERLAYSIZE__ - %S;
- MOVE: file = %O, define = yes, start = $0000, size = $FFFF;
- LC: define = yes, start = __LCADDR__, size = __LCSIZE__;
+ ZP: file = "", define = yes, start = $0080, size = $001A;
+ HEADER: file = %O, start = %S - 4, size = $0004;
+ MAIN: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = __HIMEM__ - __OVERLAYSIZE__ - %S;
+ BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__;
+ LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__;
OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__;
OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__;
OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes;
- LC: load = MOVE, run = LC, type = ro, optional = yes;
- OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
- OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
- OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
- OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
- OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
- OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
- OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
- OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
- OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro, define = 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ LC: load = MAIN, run = LC, type = ro, optional = yes;
+ BSS: load = BSS, type = bss, define = yes;
+ OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
+ OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
+ OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
+ OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
+ OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
+ OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
+ OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
+ OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
+ OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
# Configuration for ProDOS 8 system programs (without the header)
SYMBOLS {
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
__LCADDR__: type = weak, value = $D400; # Behind quit code
__LCSIZE__: type = weak, value = $0C00; # Rest of bank two
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
- __LOADADDR__: type = weak, value = __STARTUP_RUN__;
- __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ +
- __MOVE_LAST__ - __MOVE_START__;
}
MEMORY {
- ZP: define = yes, start = $0080, size = $001A;
- RAM: file = %O, start = $2000, size = $9F00 - __STACKSIZE__;
- MOVE: file = %O, define = yes, start = $0000, size = $FFFF;
- LC: define = yes, start = __LCADDR__, size = __LCSIZE__;
+ ZP: file = "", define = yes, start = $0080, size = $001A;
+ MAIN: file = %O, start = $2000, size = $BF00 - $2000;
+ BSS: file = "", start = __ONCE_RUN__, size = $BF00 - __STACKSIZE__ - __ONCE_RUN__;
+ LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes;
- LC: load = MOVE, run = LC, type = ro, optional = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ STARTUP: load = MAIN, type = ro;
+ 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ LC: load = MAIN, run = LC, type = ro, optional = yes;
+ BSS: load = BSS, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
}
SYMBOLS {
__EXEHDR__: type = import;
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
__HIMEM__: type = weak, value = $9600; # Presumed RAM end
__LCADDR__: type = weak, value = $D400; # Behind quit code
__LCSIZE__: type = weak, value = $0C00; # Rest of bank two
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
- __LOADADDR__: type = weak, value = __STARTUP_RUN__;
- __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ +
- __MOVE_LAST__ - __MOVE_START__;
}
MEMORY {
- ZP: define = yes, start = $0080, size = $001A;
- HEADER: file = %O, start = $0000, size = $0004;
- RAM: file = %O, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
- MOVE: file = %O, define = yes, start = $0000, size = $FFFF;
- LC: define = yes, start = __LCADDR__, size = __LCSIZE__;
+ ZP: file = "", define = yes, start = $0080, size = $001A;
+ HEADER: file = %O, start = %S - 4, size = $0004;
+ MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - %S;
+ BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__;
+ LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes;
- LC: load = MOVE, run = LC, type = ro, optional = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ LC: load = MAIN, run = LC, type = ro, optional = yes;
+ BSS: load = BSS, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
FEATURES {
STARTADDRESS: default = $0803;
}
-SYMBOLS {
- __LOADADDR__: type = weak, value = __CODE_RUN__;
- __LOADSIZE__: type = weak, value = __BSS_RUN__ - __CODE_RUN__;
-}
MEMORY {
- HEADER: file = %O, start = $0000, size = $0004;
- RAM: file = %O, start = %S, size = $C000 - %S;
+ ZP: file = "", start = $0000, size = $00FF;
+ HEADER: file = %O, start = %S - 4, size = $0004;
+ MAIN: file = %O, define = yes, start = %S, size = $C000 - %S;
+ BSS: file = "", start = __MAIN_LAST__, size = $C000 - __MAIN_LAST__;
}
SEGMENTS {
- EXEHDR: load = HEADER, type = ro, optional = yes;
- CODE: load = RAM, type = rw, optional = yes, define = yes;
- RODATA: load = RAM, type = ro, optional = yes;
- DATA: load = RAM, type = rw, optional = yes;
- BSS: load = RAM, type = bss, optional = yes, define = yes;
+ ZEROPAGE: load = ZP, type = zp, optional = yes;
+ EXEHDR: load = HEADER, type = ro, optional = yes;
+ CODE: load = MAIN, type = rw;
+ RODATA: load = MAIN, type = ro, optional = yes;
+ DATA: load = MAIN, type = rw, optional = yes;
+ BSS: load = BSS, type = bss, optional = yes, define = yes;
}
}
SYMBOLS {
__EXEHDR__: type = import;
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
__HIMEM__: type = weak, value = $9600; # Presumed RAM end
__LCADDR__: type = weak, value = $D400; # Behind quit code
__LCSIZE__: type = weak, value = $0C00; # Rest of bank two
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
__OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay
- __LOADADDR__: type = weak, value = __STARTUP_RUN__;
- __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ +
- __MOVE_LAST__ - __MOVE_START__;
}
MEMORY {
- ZP: define = yes, start = $0080, size = $001A;
- HEADER: file = %O, start = $0000, size = $0004;
- RAM: file = %O, start = %S + __OVERLAYSIZE__, size = __HIMEM__ - __STACKSIZE__ - __OVERLAYSIZE__ - %S;
- MOVE: file = %O, define = yes, start = $0000, size = $FFFF;
- LC: define = yes, start = __LCADDR__, size = __LCSIZE__;
+ ZP: file = "", define = yes, start = $0080, size = $001A;
+ HEADER: file = %O, start = %S - 4, size = $0004;
+ MAIN: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = __HIMEM__ - __OVERLAYSIZE__ - %S;
+ BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__;
+ LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__;
OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__;
OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__;
OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes;
- LC: load = MOVE, run = LC, type = ro, optional = yes;
- OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
- OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
- OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
- OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
- OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
- OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
- OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
- OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
- OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro, define = 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ LC: load = MAIN, run = LC, type = ro, optional = yes;
+ BSS: load = BSS, type = bss, define = yes;
+ OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
+ OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
+ OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
+ OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
+ OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
+ OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
+ OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
+ OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
+ OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
# Configuration for ProDOS 8 system programs (without the header)
SYMBOLS {
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
__LCADDR__: type = weak, value = $D400; # Behind quit code
__LCSIZE__: type = weak, value = $0C00; # Rest of bank two
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
- __LOADADDR__: type = weak, value = __STARTUP_RUN__;
- __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ +
- __MOVE_LAST__ - __MOVE_START__;
}
MEMORY {
- ZP: define = yes, start = $0080, size = $001A;
- RAM: file = %O, start = $2000, size = $9F00 - __STACKSIZE__;
- MOVE: file = %O, define = yes, start = $0000, size = $FFFF;
- LC: define = yes, start = __LCADDR__, size = __LCSIZE__;
+ ZP: file = "", define = yes, start = $0080, size = $001A;
+ MAIN: file = %O, start = $2000, size = $BF00 - $2000;
+ BSS: file = "", start = __ONCE_RUN__, size = $BF00 - __STACKSIZE__ - __ONCE_RUN__;
+ LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes;
- LC: load = MOVE, run = LC, type = ro, optional = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ STARTUP: load = MAIN, type = ro;
+ 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ LC: load = MAIN, run = LC, type = ro, optional = yes;
+ BSS: load = BSS, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
}
SYMBOLS {
__EXEHDR__: type = import;
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
__HIMEM__: type = weak, value = $9600; # Presumed RAM end
__LCADDR__: type = weak, value = $D400; # Behind quit code
__LCSIZE__: type = weak, value = $0C00; # Rest of bank two
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
- __LOADADDR__: type = weak, value = __STARTUP_RUN__;
- __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ +
- __MOVE_LAST__ - __MOVE_START__;
}
MEMORY {
- ZP: define = yes, start = $0080, size = $001A;
- HEADER: file = %O, start = $0000, size = $0004;
- RAM: file = %O, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
- MOVE: file = %O, define = yes, start = $0000, size = $FFFF;
- LC: define = yes, start = __LCADDR__, size = __LCSIZE__;
+ ZP: file = "", define = yes, start = $0080, size = $001A;
+ HEADER: file = %O, start = %S - 4, size = $0004;
+ MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - %S;
+ BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__;
+ LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes;
- LC: load = MOVE, run = LC, type = ro, optional = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ LC: load = MAIN, run = LC, type = ro, optional = yes;
+ BSS: load = BSS, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
STARTADDRESS: default = $2E00;
}
SYMBOLS {
- __EXEHDR__: type = import;
- __AUTOSTART__: type = import; # force inclusion of autostart "trailer"
- __STARTADDRESS__: type = export, value = %S;
+ __EXEHDR__: type = import;
+ __AUTOSTART__: type = import; # force inclusion of autostart "trailer"
+ __STARTADDRESS__: type = export, value = %S;
}
MEMORY {
- ZP: file = "", define = yes, start = $0082, size = $007E;
+ ZP: file = "", define = yes, start = $0082, size = $007E;
# file header, just $FFFF
- HEADER: file = %O, start = $0000, size = $0002;
+ HEADER: file = %O, start = $0000, size = $0002;
# "main program" load chunk
- MAINHDR: file = %O, start = $0000, size = $0004;
- RAM: file = %O, define = yes, start = %S, size = $BC20 - %S;
- TRAILER: file = %O, start = $0000, size = $0006;
+ MAINHDR: file = %O, start = $0000, size = $0004;
+ MAIN: file = %O, define = yes, start = %S, size = $BC20 - %S;
+ TRAILER: file = %O, start = $0000, size = $0006;
}
SEGMENTS {
- EXEHDR: load = HEADER, type = ro, optional = yes;
- MAINHDR: load = MAINHDR, type = ro, optional = yes;
- CODE: load = RAM, type = ro, define = yes, optional = yes;
- RODATA: load = RAM, type = ro optional = yes;
- DATA: load = RAM, type = rw optional = yes;
- BSS: load = RAM, type = bss, define = yes, optional = yes;
- ZEROPAGE: load = ZP, type = zp, optional = yes;
- EXTZP: load = ZP, type = zp, optional = yes; # to enable modules to be able to link to C and assembler programs
- AUTOSTRT: load = TRAILER, type = ro, optional = yes;
+ ZEROPAGE: load = ZP, type = zp, optional = yes;
+ EXTZP: load = ZP, type = zp, optional = yes; # to enable modules to be able to link to C and assembler programs
+ EXEHDR: load = HEADER, type = ro, optional = yes;
+ MAINHDR: load = MAINHDR, type = ro, optional = yes;
+ CODE: load = MAIN, type = rw, define = yes;
+ RODATA: load = MAIN, type = ro optional = yes;
+ DATA: load = MAIN, type = rw optional = yes;
+ BSS: load = MAIN, type = bss, optional = yes, define = yes;
+ AUTOSTRT: load = TRAILER, type = ro, optional = yes;
}
__CARTFLAGS__: type = weak, value = $01; # see documentation for other possible values
}
MEMORY {
- ZP: file = "", define = yes, start = $0082, size = $007E;
- RAM: file = "", define = yes, start = %S, size = __CARTSIZE__;
- ROM: file = %O, define = yes, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - 6, fill = yes, fillval = $FF;
- CARTID: file = %O, start = $BFFA, size = $0006;
+ ZP: file = "", define = yes, start = $0082, size = $007E;
+ MAIN: file = "", define = yes, start = %S, size = __CARTSIZE__;
+ ROM: file = %O, define = yes, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - 6, fill = yes, fillval = $FF;
+ CARTID: file = %O, start = $BFFA, size = $0006;
}
SEGMENTS {
- STARTUP: load = ROM, type = ro, define = yes, optional = yes;
- LOWCODE: load = ROM, type = ro, define = yes, optional = yes;
- INIT: load = ROM, type = ro, optional = yes;
- CODE: load = ROM, type = ro, define = yes;
- RODATA: load = ROM, type = ro, optional = yes;
- DATA: load = ROM, run = RAM, type = rw, define = yes, optional = yes;
- INITBSS: load = RAM, type = bss, optional = yes;
- BSS: load = RAM, type = bss, define = yes, optional = yes;
- CARTHDR: load = CARTID, type = ro;
- ZEROPAGE: load = ZP, type = zp, optional = yes;
- EXTZP: load = ZP, type = zp, optional = yes;
+ ZEROPAGE: load = ZP, type = zp, optional = yes;
+ EXTZP: load = ZP, type = zp, optional = yes;
+ STARTUP: load = ROM, type = ro, define = yes, optional = yes;
+ LOWCODE: load = ROM, type = ro, define = yes, optional = yes;
+ ONCE: load = ROM, type = ro, optional = yes;
+ CODE: load = ROM, type = ro, define = yes;
+ RODATA: load = ROM, type = ro, optional = yes;
+ DATA: load = ROM, run = MAIN, type = rw, define = yes, optional = yes;
+ INIT: load = MAIN, type = bss, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes, optional = yes;
+ CARTHDR: load = CARTID, type = ro;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
_cas_hdr: type = import;
}
MEMORY {
- ZP: file = "", define = yes, start = $0082, size = $007E;
- RAM: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
+ ZP: file = "", define = yes, start = $0082, size = $007E;
+ MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
}
SEGMENTS {
- CASHDR: load = RAM, type = ro;
- STARTUP: load = RAM, type = ro, define = yes, optional = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro, optional = yes;
- DATA: load = RAM, type = rw, optional = yes;
- INITBSS: load = RAM, type = bss, optional = yes;
- BSS: load = RAM, type = bss, define = yes, optional = yes;
- ZEROPAGE: load = ZP, type = zp, optional = yes;
- EXTZP: load = ZP, type = zp, optional = yes;
+ ZEROPAGE: load = ZP, type = zp, optional = yes;
+ EXTZP: load = ZP, type = zp, optional = yes;
+ CASHDR: load = MAIN, type = ro;
+ STARTUP: load = MAIN, type = ro, define = yes, optional = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro, optional = yes;
+ DATA: load = MAIN, type = rw, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes, optional = yes;
+ INIT: load = MAIN, type = bss, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__RESERVED_MEMORY__: type = weak, value = $0000;
}
MEMORY {
- ZP: file = "", define = yes, start = $0082, size = $007E;
+ ZP: file = "", define = yes, start = $0082, size = $007E;
# file header, just $FFFF
- HEADER: file = %O, start = $0000, size = $0002;
+ HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
- SYSCHKHDR: file = %O, start = $0000, size = $0004;
- SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
- SYSCHKTRL: file = %O, start = $0000, size = $0006;
+ SYSCHKHDR: file = %O, start = $0000, size = $0004;
+ SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
+ SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
- MAINHDR: file = %O, start = $0000, size = $0004;
- RAM: file = %O, define = yes, start = %S + __OVERLAYSIZE__,
- size = $BC20 - __OVERLAYSIZE__ - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
- TRAILER: file = %O, start = $0000, size = $0006;
+ MAINHDR: file = %O, start = $0000, size = $0004;
+ MAIN: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = $BC20 - __OVERLAYSIZE__ - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
+ TRAILER: file = %O, start = $0000, size = $0006;
- OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
- OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__;
- OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__;
- OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__;
- OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__;
- OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__;
- OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__;
- OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__;
- OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__;
+# overlays
+ OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
+ OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__;
+ OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__;
+ OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__;
+ OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__;
+ OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__;
+ OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__;
+ OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__;
+ OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
+ EXTZP: load = ZP, type = zp, optional = yes;
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes;
MAINHDR: load = MAINHDR, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, optional = yes;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
- EXTZP: load = ZP, type = zp, optional = yes;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ INIT: load = MAIN, type = rw, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes;
AUTOSTRT: load = TRAILER, type = ro;
OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__RESERVED_MEMORY__: type = weak, value = $0000;
}
MEMORY {
- ZP: file = "", define = yes, start = $0082, size = $007E;
+ ZP: file = "", define = yes, start = $0082, size = $007E;
# file header, just $FFFF
- HEADER: file = %O, start = $0000, size = $0002;
+ HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
- SYSCHKHDR: file = %O, start = $0000, size = $0004;
- SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
- SYSCHKTRL: file = %O, start = $0000, size = $0006;
+ SYSCHKHDR: file = %O, start = $0000, size = $0004;
+ SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
+ SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
- MAINHDR: file = %O, start = $0000, size = $0004;
- RAM: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
- TRAILER: file = %O, start = $0000, size = $0006;
+ MAINHDR: file = %O, start = $0000, size = $0004;
+ MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
+ TRAILER: file = %O, start = $0000, size = $0006;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
+ EXTZP: load = ZP, type = zp, optional = yes;
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes;
MAINHDR: load = MAINHDR, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, optional = yes;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
- EXTZP: load = ZP, type = zp, optional = yes;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ INIT: load = MAIN, type = rw, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes;
AUTOSTRT: load = TRAILER, type = ro;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
--- /dev/null
+# Atari VCS 2600 linker configuration file for cc65
+#
+# Florent Flament (contact@florentflament.com), 2017
+
+SYMBOLS {
+ __STACKSIZE__: type = weak, value = $0010; # 16 Bytes system stack
+}
+
+MEMORY {
+ RAM: file = "", start = $0080, size = $0080 - __STACKSIZE__, define = yes;
+ ROM: file = %O, start = $F000, size = $1000, fill = yes, fillval = $FF;
+}
+
+SEGMENTS {
+ ZEROPAGE: load = RAM, type = zp;
+ STARTUP: load = ROM, type = ro;
+ CODE: load = ROM, type = ro;
+ RODATA: load = ROM, type = ro, optional = yes;
+ DATA: load = ROM, run = RAM, type = rw, optional = yes, define = yes;
+ BSS: load = RAM, type = bss, optional = yes;
+ VECTORS: load = ROM, type = ro, start = $FFFA;
+}
CARTENTRY: file = %O, start = $BFFE, size = $0002;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp, optional = yes;
+ EXTZP: load = ZP, type = zp, optional = yes;
STARTUP: load = ROM, type = ro, define = yes, optional = yes;
LOWCODE: load = ROM, type = ro, define = yes, optional = yes;
- INIT: load = ROM, type = ro, optional = yes;
+ ONCE: load = ROM, type = ro, optional = yes;
CODE: load = ROM, type = ro, define = yes;
RODATA: load = ROM, type = ro, optional = yes;
DATA: load = ROM, run = RAM, type = rw, define = yes, optional = yes;
CARTNAME: load = CARTNAME, type = ro, define = yes;
CARTYEAR: load = CARTYEAR, type = ro, define = yes;
CARTENTRY: load = CARTENTRY, type = ro, define = yes;
- ZEROPAGE: load = ZP, type = zp, optional = yes;
- EXTZP: load = ZP, type = zp, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
FEATURES {
STARTADDRESS: default = $2400;
}
-
SYMBOLS {
- __EXEHDR__: type = import;
- __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
- __AUTOSTART__: type = import; # force inclusion of autostart "trailer"
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
- __STARTADDRESS__: type = export, value = %S;
+ __EXEHDR__: type = import;
+ __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
+ __AUTOSTART__: type = import; # force inclusion of autostart "trailer"
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
+ __STARTADDRESS__: type = export, value = %S;
}
-
MEMORY {
- ZP: file = "", define = yes, start = $0082, size = $007E;
+ ZP: file = "", define = yes, start = $0082, size = $007E;
# just $FFFF
- HEADER: file = %O, start = $0000, size = $0002;
+ HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
- SYSCHKHDR: file = %O, start = $0000, size = $0004;
- SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
- SYSCHKTRL: file = %O, start = $0000, size = $0006;
+ SYSCHKHDR: file = %O, start = $0000, size = $0004;
+ SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
+ SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "shadow RAM preparation" load chunk
- SRPREPHDR: file = %O, start = $0000, size = $0004;
- SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
- SRPREPTRL: file = %O, start = $0000, size = $0006;
+ SRPREPHDR: file = %O, start = $0000, size = $0004;
+ SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
+ SRPREPTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
- MAINHDR: file = %O, start = $0000, size = $0004;
- RAM: file = %O, define = yes, start = %S +
- __LOWBSS_SIZE__, size = $D000 -
- __STACKSIZE__ -
- %S -
- __LOWBSS_SIZE__;
+ MAINHDR: file = %O, start = $0000, size = $0004;
+ MAIN: file = %O, define = yes, start = %S + __LOWBSS_SIZE__, size = $D000 - __STACKSIZE__ - %S - __LOWBSS_SIZE__;
# defines entry point into program
- TRAILER: file = %O, start = $0000, size = $0006;
+ 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 = $0400;
# memory beneath the ROM
- HIDDEN_RAM: file = "", define = yes, start = $DC00, size = $FFFA - $DC00;
+ HIDDEN_RAM: file = "", define = yes, start = $DC00, size = $FFFA - $DC00;
}
-
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
+ EXTZP: load = ZP, type = zp, optional = yes;
+
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SRPREPTRL: load = SRPREPTRL, type = ro;
MAINHDR: load = MAINHDR, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, optional = yes;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
- EXTZP: load = ZP, type = zp, optional = yes;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ INIT: load = MAIN, type = rw, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes;
AUTOSTRT: load = TRAILER, type = ro;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
FEATURES {
STARTADDRESS: default = $2400;
}
-
SYMBOLS {
- __EXEHDR__: type = import;
- __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
- __AUTOSTART__: type = import; # force inclusion of autostart "trailer"
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
- __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay
- __STARTADDRESS__: type = export, value = %S;
+ __EXEHDR__: type = import;
+ __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
+ __AUTOSTART__: type = import; # force inclusion of autostart "trailer"
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
+ __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay
+ __STARTADDRESS__: type = export, value = %S;
}
-
MEMORY {
- ZP: file = "", define = yes, start = $0082, size = $007E;
+ ZP: file = "", define = yes, start = $0082, size = $007E;
# just $FFFF
- HEADER: file = %O, start = $0000, size = $0002;
+ HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
- SYSCHKHDR: file = %O, start = $0000, size = $0004;
- SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
- SYSCHKTRL: file = %O, start = $0000, size = $0006;
+ SYSCHKHDR: file = %O, start = $0000, size = $0004;
+ SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
+ SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "shadow RAM preparation" load chunk
- SRPREPHDR: file = %O, start = $0000, size = $0004;
- SRPREPCHNK: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = $7C20 - %S - __OVERLAYSIZE__ - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
- SRPREPTRL: file = %O, start = $0000, size = $0006;
+ SRPREPHDR: file = %O, start = $0000, size = $0004;
+ SRPREPCHNK: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = $7C20 - %S - __OVERLAYSIZE__ - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
+ SRPREPTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
- MAINHDR: file = %O, start = $0000, size = $0004;
- RAM: file = %O, define = yes, start = %S +
- __OVERLAYSIZE__ +
- __LOWBSS_SIZE__, size = $D000 -
- __STACKSIZE__ -
- %S -
- __OVERLAYSIZE__ -
- __LOWBSS_SIZE__;
+ MAINHDR: file = %O, start = $0000, size = $0004;
+ MAIN: file = %O, define = yes, start = %S + __OVERLAYSIZE__ +
+ __LOWBSS_SIZE__, size = $D000 - __STACKSIZE__ - %S - __OVERLAYSIZE__ - __LOWBSS_SIZE__;
# defines entry point into program
- TRAILER: file = %O, start = $0000, size = $0006;
+ TRAILER: file = %O, start = $0000, size = $0006;
# memory beneath the ROM preceeding the character generator
- HIDDEN_RAM2: file = "", define = yes, start = $D800, size = $0800;
+ 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 = $0400;
# memory beneath the ROM
- HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400;
+ HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400;
# overlays
- OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
- OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__;
- OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__;
- OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__;
- OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__;
- OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__;
- OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__;
- OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__;
- OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__;
+ OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__;
+ OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__;
+ OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__;
+ OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__;
+ OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__;
+ OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__;
+ OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__;
+ OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__;
+ OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__;
}
-
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
+ EXTZP: load = ZP, type = zp, optional = yes;
+
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SRPREPTRL: load = SRPREPTRL, type = ro;
MAINHDR: load = MAINHDR, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, optional = yes;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
- EXTZP: load = ZP, type = zp, optional = yes;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ INIT: load = MAIN, type = rw, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes;
AUTOSTRT: load = TRAILER, type = ro;
OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
FEATURES {
STARTADDRESS: default = $2400;
}
-
SYMBOLS {
- __EXEHDR__: type = import;
- __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
- __AUTOSTART__: type = import; # force inclusion of autostart "trailer"
- __STACKSIZE__: type = weak, value = $0800; # 2k stack
- __STARTADDRESS__: type = export, value = %S;
+ __EXEHDR__: type = import;
+ __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
+ __AUTOSTART__: type = import; # force inclusion of autostart "trailer"
+ __STACKSIZE__: type = weak, value = $0800; # 2k stack
+ __STARTADDRESS__: type = export, value = %S;
}
-
MEMORY {
- ZP: file = "", define = yes, start = $0082, size = $007E;
+ ZP: file = "", define = yes, start = $0082, size = $007E;
# just $FFFF
- HEADER: file = %O, start = $0000, size = $0002;
+ HEADER: file = %O, start = $0000, size = $0002;
# "system check" load chunk
- SYSCHKHDR: file = %O, start = $0000, size = $0004;
- SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
- SYSCHKTRL: file = %O, start = $0000, size = $0006;
+ SYSCHKHDR: file = %O, start = $0000, size = $0004;
+ SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
+ SYSCHKTRL: file = %O, start = $0000, size = $0006;
# "shadow RAM preparation" load chunk
- SRPREPHDR: file = %O, start = $0000, size = $0004;
- SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
- SRPREPTRL: file = %O, start = $0000, size = $0006;
+ SRPREPHDR: file = %O, start = $0000, size = $0004;
+ SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
+ SRPREPTRL: file = %O, start = $0000, size = $0006;
# "main program" load chunk
- MAINHDR: file = %O, start = $0000, size = $0004;
- RAM: file = %O, define = yes, start = %S +
- __LOWBSS_SIZE__, size = $D000 -
- __STACKSIZE__ -
- %S -
- __LOWBSS_SIZE__;
+ MAINHDR: file = %O, start = $0000, size = $0004;
+ MAIN: file = %O, define = yes, start = %S + __LOWBSS_SIZE__, size = $D000 - __STACKSIZE__ - %S - __LOWBSS_SIZE__;
# defines entry point into program
- TRAILER: file = %O, start = $0000, size = $0006;
+ TRAILER: file = %O, start = $0000, size = $0006;
# memory beneath the ROM preceeding the character generator
- HIDDEN_RAM2: file = "", define = yes, start = $D800, size = $0800;
+ 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 = $0400;
# memory beneath the ROM
- HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400;
+ HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400;
}
-
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
+ EXTZP: load = ZP, type = zp, optional = yes;
+
EXEHDR: load = HEADER, type = ro;
SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes;
SRPREPTRL: load = SRPREPTRL, type = ro;
MAINHDR: load = MAINHDR, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss, optional = yes;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
- EXTZP: load = ZP, type = zp, optional = yes;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ INIT: load = MAIN, type = rw, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes;
AUTOSTRT: load = TRAILER, type = ro;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__RAMEND__: type = weak, value = $9800 + $1C00 * __GRAB__;
}
MEMORY {
- ZP: file = "", define = yes, start = $00E2, size = $001A;
- TAPEHDR: file = %O, type = ro, start = $0000, size = $001F;
- BASHEAD: file = %O, define = yes, start = $0501, size = $000D;
- RAM: file = %O, define = yes, start = __BASHEAD_LAST__, size = __RAMEND__ - __RAM_START__ - __STACKSIZE__;
+ ZP: file = "", define = yes, start = $00E2, size = $001A;
+ TAPEHDR: file = %O, type = ro, start = $0000, size = $001F;
+ BASHEAD: file = %O, define = yes, start = $0501, size = $000D;
+ MAIN: file = %O, define = yes, start = __BASHEAD_LAST__, size = __RAMEND__ - __MAIN_START__;
+ BSS: file = "", start = __ONCE_RUN__, size = __RAMEND__ - __STACKSIZE__ - __ONCE_RUN__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
TAPEHDR: load = TAPEHDR, type = ro;
- BASHDR: load = BASHEAD, type = ro, define = yes, optional = yes;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- DATA: load = RAM, type = rw;
- ZPSAVE1: load = RAM, type = rw, define = yes; # ZPSAVE1, ZPSAVE2 must be together
- ZPSAVE2: load = RAM, type = bss; # see "libsrc/atmos/crt0.s"
- BSS: load = RAM, type = bss, define = yes;
+ BASHDR: load = BASHEAD, type = ro, optional = yes;
+ STARTUP: load = MAIN, type = ro;
+ 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ BASTAIL: load = MAIN, type = ro, optional = yes;
+ BSS: load = BSS, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__STACKSIZE__: type = weak, value = $0800; # 2k stack
}
MEMORY {
- ZP: file = "", define = yes, start = $0070, size = $0020;
- RAM: file = %O, start = $0E00, size = $7200 - __STACKSIZE__;
+ ZP: file = "", define = yes, start = $0070, size = $0020;
+ MAIN: file = %O, start = $0E00, size = $7200 - __STACKSIZE__;
}
SEGMENTS {
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ ZEROPAGE: load = ZP, type = zp;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = $1BFF, size = $0002;
HEADER: file = %O, start = $1C01, size = $000C;
- RAM: file = %O, define = yes, start = $1C0D, size = $A3F3 - __OVERLAYSIZE__ - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $1C0D, size = $A3F3 - __OVERLAYSIZE__ - __STACKSIZE__;
OVL1ADDR: file = "%O.1", start = $BFFE - __OVERLAYSIZE__, size = $0002;
OVL1: file = "%O.1", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
OVL2ADDR: file = "%O.2", start = $BFFE - __OVERLAYSIZE__, size = $0002;
OVL9: file = "%O.9", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: 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 = bss;
+ BSS: load = MAIN, type = bss, define = yes;
OVL1ADDR: load = OVL1ADDR, type = ro;
OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
OVL2ADDR: load = OVL2ADDR, type = ro;
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = $1BFF, size = $0002;
HEADER: file = %O, start = $1C01, size = $000C;
- RAM: file = %O, define = yes, start = $1C0D, size = $A3F3 - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $1C0D, size = $A3F3 - __STACKSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: 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 = bss;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = $0FFF, size = $0002;
HEADER: file = %O, start = $1001, size = $000C;
- RAM: file = %O, start = $100D, size = $6FF3 - __STACKSIZE__;
+ MAIN: file = %O, start = $100D, size = $6FF3 - __STACKSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: 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 = bss;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__LOADADDR__: type = import;
}
MEMORY {
- ZP: file = "", start = $0002, size = $001A, define = yes;
+ ZP: file = "", start = $0002, size = $00FE, define = yes;
LOADADDR: file = %O, start = %S - 2, size = $0002;
- RAM: file = %O, start = %S, size = $D000 - %S;
+ MAIN: file = %O, start = %S, size = $D000 - %S;
}
SEGMENTS {
- LOADADDR: load = LOADADDR, type = ro;
- EXEHDR: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = rw, optional = yes;
- RODATA: load = RAM, type = ro, optional = yes;
- DATA: load = RAM, type = rw, optional = yes;
- BSS: load = RAM, type = bss, optional = yes;
ZEROPAGE: load = ZP, type = zp, optional = yes;
+ LOADADDR: load = LOADADDR, type = ro;
+ EXEHDR: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = rw;
+ RODATA: load = MAIN, type = ro, optional = yes;
+ DATA: load = MAIN, type = rw, optional = yes;
+ BSS: load = MAIN, type = bss, optional = yes, define = yes;
}
FEATURES {
- STARTADDRESS: default = $0801;
+ STARTADDRESS: default = $0801;
}
SYMBOLS {
__LOADADDR__: type = import;
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = %S - 2, size = $0002;
HEADER: file = %O, define = yes, start = %S, size = $000D;
- MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __OVERLAYSTART__ - __STACKSIZE__ - __HEADER_LAST__;
- MOVE: file = %O, start = __INITBSS_LOAD__, size = __HIMEM__ - __BSS_RUN__;
- INIT: file = "", start = __BSS_RUN__, size = __HIMEM__ - __BSS_RUN__;
+ MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __HEADER_LAST__;
+ BSS: file = "", start = __ONCE_RUN__, size = __OVERLAYSTART__ - __STACKSIZE__ - __ONCE_RUN__;
OVL1ADDR: file = "%O.1", start = __OVERLAYSTART__ - 2, size = $0002;
OVL1: file = "%O.1", start = __OVERLAYSTART__, size = __OVERLAYSIZE__;
OVL2ADDR: file = "%O.2", start = __OVERLAYSTART__ - 2, size = $0002;
OVL9: file = "%O.9", start = __OVERLAYSTART__, size = __OVERLAYSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- LOADADDR: load = LOADADDR, type = ro;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = MAIN, type = ro;
- LOWCODE: load = MAIN, type = ro, optional = yes;
- CODE: load = MAIN, type = ro;
- RODATA: load = MAIN, type = ro;
- DATA: load = MAIN, type = rw;
- INITBSS: load = MAIN, type = bss, define = yes;
- BSS: load = MAIN, type = bss, define = yes;
- INIT: load = MOVE, run = INIT, type = ro, define = yes;
- OVL1ADDR: load = OVL1ADDR, type = ro;
- OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
- OVL2ADDR: load = OVL2ADDR, type = ro;
- OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
- OVL3ADDR: load = OVL3ADDR, type = ro;
- OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
- OVL4ADDR: load = OVL4ADDR, type = ro;
- OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
- OVL5ADDR: load = OVL5ADDR, type = ro;
- OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
- OVL6ADDR: load = OVL6ADDR, type = ro;
- OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
- OVL7ADDR: load = OVL7ADDR, type = ro;
- OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
- OVL8ADDR: load = OVL8ADDR, type = ro;
- OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
- OVL9ADDR: load = OVL9ADDR, type = ro;
- OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ LOADADDR: load = LOADADDR, type = ro;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ BSS: load = BSS, type = bss, define = yes;
+ OVL1ADDR: load = OVL1ADDR, type = ro;
+ OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
+ OVL2ADDR: load = OVL2ADDR, type = ro;
+ OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
+ OVL3ADDR: load = OVL3ADDR, type = ro;
+ OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
+ OVL4ADDR: load = OVL4ADDR, type = ro;
+ OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
+ OVL5ADDR: load = OVL5ADDR, type = ro;
+ OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
+ OVL6ADDR: load = OVL6ADDR, type = ro;
+ OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
+ OVL7ADDR: load = OVL7ADDR, type = ro;
+ OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
+ OVL8ADDR: load = OVL8ADDR, type = ro;
+ OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
+ OVL9ADDR: load = OVL9ADDR, type = ro;
+ OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
FEATURES {
- STARTADDRESS: default = $0801;
+ STARTADDRESS: default = $0801;
}
SYMBOLS {
__LOADADDR__: type = import;
__HIMEM__: type = weak, value = $D000;
}
MEMORY {
- ZP: file = "", define = yes, start = $0002, size = $001A;
- LOADADDR: file = %O, start = %S - 2, size = $0002;
- HEADER: file = %O, define = yes, start = %S, size = $000D;
- MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __STACKSIZE__ - __HEADER_LAST__;
- MOVE: file = %O, start = __INITBSS_LOAD__, size = __HIMEM__ - __BSS_RUN__;
- INIT: file = "", start = __BSS_RUN__, size = __HIMEM__ - __BSS_RUN__;
+ ZP: file = "", define = yes, start = $0002, size = $001A;
+ LOADADDR: file = %O, start = %S - 2, size = $0002;
+ 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__ - __STACKSIZE__ - __ONCE_RUN__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- LOADADDR: load = LOADADDR, type = ro;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = MAIN, type = ro;
- LOWCODE: load = MAIN, type = ro, optional = yes;
- CODE: load = MAIN, type = ro;
- RODATA: load = MAIN, type = ro;
- DATA: load = MAIN, type = rw;
- INITBSS: load = MAIN, type = bss, define = yes;
- BSS: load = MAIN, type = bss, define = yes;
- INIT: load = MOVE, run = INIT, type = ro, define = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ LOADADDR: load = LOADADDR, type = ro;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ 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;
+ ONCE: load = MAIN, type = ro, define = yes;
+ BSS: load = BSS, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
STARTUP: file = %O, start = $00FE, size = $0102, fill = yes;
PAGE2: file = %O, start = $0200, size = $0100, fill = yes;
PAGE3: file = %O, start = $0300, size = $0100, fill = yes;
- RAM: file = %O, start = $0400, size = $DC00;
+ MAIN: file = %O, start = $0400, size = $DC00;
CHARRAM: file = "", define = yes, start = $E000, size = $1000;
VIDRAM: file = "", define = yes, start = $F000, size = $0400;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
+ EXTZP: load = ZP, type = rw, define = yes;
EXEHDR: load = HEADER, type = rw;
STARTUP: load = STARTUP, type = rw;
PAGE2: load = PAGE2, type = rw;
PAGE3: load = PAGE3, type = rw;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
- EXTZP: load = ZP, type = rw, define = yes;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: 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 = bss, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
STARTUP: file = %O, start = $00FE, size = $0102, fill = yes;
PAGE2: file = %O, start = $0200, size = $0100, fill = yes;
PAGE3: file = %O, start = $0300, size = $0100, fill = yes;
- RAM: file = %O, start = $0400, size = $FECB - __STACKSIZE__;
+ MAIN: file = %O, start = $0400, size = $FECB - __STACKSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
+ EXTZP: load = ZP, type = rw, define = yes;
EXEHDR: load = HEADER, type = rw;
STARTUP: load = STARTUP, type = rw;
PAGE2: load = PAGE2, type = rw;
PAGE3: load = PAGE3, type = rw;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
- EXTZP: load = ZP, type = rw, define = yes;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: 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 = bss, optional = yes;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
# linker config to produce simple Gamate cartridge (.bin)
SYMBOLS {
- __STARTUP__: type = import;
- __STACKSIZE__: type = weak, value = $0080; # 1 page stack
+ __STARTUP__: type = import;
+ __STACKSIZE__: type = weak, value = $0080; # 1 page stack
}
MEMORY {
- # 0000-03ff is RAM
- # FIXME: what zp range can we actually use?
- # $0a-$11 is used by IRQ/NMI, $e8 is used by NMI
- ZP: start = $0012, size = $e8 - $12;
- CPUSTACK: start = $0100, size =$100;
- RAM: start = $0200, size = $200 - __STACKSIZE__, define = yes;
+ # 0000-03ff is RAM
+ # FIXME: what zp range can we actually use?
+ # $0a-$11 is used by IRQ/NMI, $e8 is used by NMI
+ ZP: start = $0012, size = $00E8 - $0012;
+ CPUSTACK: start = $0100, size = $0100;
+ RAM: start = $0200, size = $0200 - __STACKSIZE__, define = yes;
- CARTHEADER: file = %O, define = yes, start = %S, size = $0029;
- # 6000-e000 can be (Cartridge) ROM
- # WARNING: fill value must be $00 else it will no more work
- #ROM: start = $6000, size = $1000, fill = yes, fillval = $00, file = %O, define = yes;
- #ROMFILL: start = $7000, size = $7000, fill = yes, fillval = $00, file = %O, define = yes;
- # for images that have code >$6fff we must calculate the checksum!
- ROM: start = $6000 + $29, size = $8000 - $29, fill = yes, fillval = $00, file = %O, define = yes;
+ CARTHEADER: file = %O, define = yes, start = %S, size = $0029;
+ # 6000-e000 can be (Cartridge) ROM
+ # WARNING: fill value must be $00 else it will no more work
+ #ROM: start = $6000, size = $1000, fill = yes, fillval = $00, file = %O, define = yes;
+ #ROMFILL: start = $7000, size = $7000, fill = yes, fillval = $00, file = %O, define = yes;
+ # for images that have code >$6fff we must calculate the checksum!
+ ROM: start = $6000 + $0029, size = $8000 - $0029, fill = yes, fillval = $00, file = %O, define = yes;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp, define = yes;
- EXTZP: load = ZP, type = zp, define = yes, optional = yes;
- APPZP: load = ZP, type = zp, define = yes, optional = yes;
- STARTUP: load = CARTHEADER, type = ro, define=yes;
- INIT: load = ROM, type = ro, define = yes, optional = yes;
- CODE: load = ROM, type = ro, define=yes;
- RODATA: load = ROM, type = ro, define=yes;
- DATA: load = ROM, run=RAM, type = rw, define = yes;
- BSS: load = RAM, type = bss, define = yes;
+ ZEROPAGE: load = ZP, type = zp, define = yes;
+ EXTZP: load = ZP, type = zp, define = yes, optional = yes;
+ APPZP: load = ZP, type = zp, define = yes, optional = yes;
+ STARTUP: load = CARTHEADER, type = ro, define = yes;
+ ONCE: load = ROM, type = ro, optional = yes;
+ CODE: load = ROM, type = ro, define = yes;
+ RODATA: load = ROM, type = ro, define = yes;
+ DATA: load = ROM, run = RAM, type = rw, define = yes;
+ BSS: load = RAM, type = bss, define = yes;
}
FEATURES {
- CONDES: segment = RODATA, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__;
- CONDES: segment = RODATA, type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__;
- CONDES: segment = RODATA, type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, import = __CALLIRQ__;
+ 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__;
}
}
SEGMENTS {
ZEROPAGE: type = zp, load = ZP;
- EXTZP: type = zp, load = ZP, optional = yes;
+ EXTZP: type = zp, load = ZP, optional = yes;
EXTBSS: type = bss, load = EXT, define = yes, optional = yes;
FILEINFO: type = ro, load = CVT, offset = $002;
RECORDS: type = ro, load = CVT, offset = $100, optional = yes;
VLIRIDX0: type = ro, load = CVT, align = $200, optional = yes;
STARTUP: type = ro, run = VLIR0, load = CVT, align_load = $200, define = yes;
LOWCODE: type = ro, run = VLIR0, load = CVT, optional = yes;
- INIT: type = ro, run = VLIR0, load = CVT, define = yes, optional = yes;
+ ONCE: type = ro, run = VLIR0, load = CVT, optional = yes;
CODE: type = ro, run = VLIR0, load = CVT;
RODATA: type = ro, run = VLIR0, load = CVT;
DATA: type = rw, run = VLIR0, load = CVT;
- BSS: type = bss, load = VLIR0, define = yes;
+ INIT: type = bss, load = VLIR0, optional = yes;
+ BSS: type = bss, load = VLIR0, define = yes;
VLIRIDX1: type = ro, load = CVT, align = $200, optional = yes;
OVERLAY1: type = ro, run = VLIR1, load = CVT, align_load = $200, optional = yes;
VLIRIDX2: type = ro, load = CVT, align = $200, optional = yes;
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
}
SEGMENTS {
ZEROPAGE: type = zp, load = ZP;
- EXTZP: type = zp, load = ZP, optional = yes;
+ EXTZP: type = zp, load = ZP, optional = yes;
DIRENTRY: type = ro, load = CVT, align = $FE;
FILEINFO: type = ro, load = CVT, align = $FE;
RECORDS: type = ro, load = CVT, align = $FE, optional = yes;
STARTUP: type = ro, run = VLIR0, load = CVT, align_load = $FE, define = yes;
LOWCODE: type = ro, run = VLIR0, load = CVT, optional = yes;
- INIT: type = ro, run = VLIR0, load = CVT, define = yes, optional = yes;
+ ONCE: type = ro, run = VLIR0, load = CVT, optional = yes;
CODE: type = ro, run = VLIR0, load = CVT;
RODATA: type = ro, run = VLIR0, load = CVT;
DATA: type = rw, run = VLIR0, load = CVT;
- BSS: type = bss, load = VLIR0, define = yes;
+ INIT: type = bss, load = VLIR0, optional = yes;
+ BSS: type = bss, load = VLIR0, define = yes;
OVERLAY1: type = ro, run = VLIR1, load = CVT, align_load = $FE, optional = yes;
OVERLAY2: type = ro, run = VLIR2, load = CVT, align_load = $FE, optional = yes;
OVERLAY3: type = ro, run = VLIR3, load = CVT, align_load = $FE, optional = yes;
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__STACKSIZE__: type = weak, value = $0400; # 1k stack (do typical LUnix apps. need 2k?)
}
MEMORY {
- ZP: start = $0080, size = $0040;
- RAM: start = %S, size = $7600 - __STACKSIZE__;
+ ZP: start = $0080, size = $0040;
+ MAIN: start = %S, size = $7600 - __STACKSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp, define = yes; # Pseudo-registers
- STARTUP: load = RAM, type = ro; # First initialization code
- LOWCODE: load = RAM, type = ro, optional = yes; # Legacy from other platforms
- INIT: load = RAM, type = ro, define = yes, optional = yes; # Library initialization code
- CODE: load = RAM, type = ro; # Program
- RODATA: load = RAM, type = ro; # Literals, constants
- DATA: load = RAM, type = rw; # Initialized variables
- BSS: load = RAM, type = bss, define = yes; # Uninitialized variables
+ ZEROPAGE: load = ZP, type = zp, define = yes; # Pseudo-registers
+ STARTUP: load = MAIN, type = ro; # First initialization code
+ LOWCODE: load = MAIN, type = ro, optional = yes; # Legacy from other platforms
+ ONCE: load = MAIN, type = ro, optional = yes; # Library initialization code
+ CODE: load = MAIN, type = ro; # Program
+ RODATA: load = MAIN, type = ro; # Literals, constants
+ DATA: load = MAIN, type = rw; # Initialized variables
+ BSS: load = MAIN, type = bss, define = yes; # Uninitialized variables
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader
- __BLOCKSIZE__: type = weak, value = $0400; # cart block size
+ __BANK0BLOCKSIZE__: type = weak, value = $0400; # bank 0 cart block size
+ __BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size
__BLLHDR__: type = import;
}
MEMORY {
ZP: file = "", define = yes, start = $0000, size = $0100;
HEADER: file = %O, start = $0000, size = $000a;
- RAM: file = %O, define = yes, start = $0400, size = $BC38 - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $0400, size = $BC38 - __STACKSIZE__;
}
SEGMENTS {
- BLLHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro, define = yes;
- DATA: load = RAM, type = rw, define = yes;
- BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
APPZP: load = ZP, type = zp, optional = yes;
+ BLLHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, define = yes, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro, define = yes;
+ DATA: load = MAIN, type = rw, define = yes;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader
- __BLOCKSIZE__: type = weak, value = $0400; # cart block size
+ __BANK0BLOCKSIZE__: type = weak, value = $0400; # bank 0 cart block size
+ __BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size
__EXEHDR__: type = import;
__BOOTLDR__: type = import;
__DEFDIR__: type = import;
HEADER: file = %O, start = $0000, size = $0040;
BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__;
DIR: file = %O, start = $0000, size = 8;
- RAM: file = %O, define = yes, start = $0200, size = $9E58 - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $0200, size = $9E58 - __STACKSIZE__;
}
SEGMENTS {
- EXEHDR: load = HEADER, type = ro;
- BOOTLDR: load = BOOT, type = ro;
- DIRECTORY: load = DIR, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro, define = yes;
- DATA: load = RAM, type = rw, define = yes;
- BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
APPZP: load = ZP, type = zp, optional = yes;
+ EXEHDR: load = HEADER, type = ro;
+ BOOTLDR: load = BOOT, type = ro;
+ DIRECTORY: load = DIR, type = ro;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, define = yes, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro, define = yes;
+ DATA: load = MAIN, type = rw, define = yes;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader
- __BLOCKSIZE__: type = weak, value = $0400; # cart block size
+ __BANK0BLOCKSIZE__: type = weak, value = $0400; # bank 0 cart block size
+ __BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size
__EXEHDR__: type = import;
__BOOTLDR__: type = import;
__DEFDIR__: type = import;
HEADER: file = %O, start = $0000, size = $0040;
BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__;
DIR: file = %O, start = $0000, size = 8;
- RAM: file = %O, define = yes, start = $0200, size = $BD38 - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $0200, size = $BD38 - __STACKSIZE__;
UPLDR: file = %O, define = yes, start = $BFDC, size = $005C;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
+ EXTZP: load = ZP, type = zp, optional = yes;
+ APPZP: load = ZP, type = zp, optional = yes;
EXEHDR: load = HEADER, type = ro;
BOOTLDR: load = BOOT, type = ro;
DIRECTORY:load = DIR, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro, define = yes;
- DATA: load = RAM, type = rw, define = yes;
- BSS: load = RAM, type = bss, define = yes;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, define = yes, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro, define = yes;
+ DATA: load = MAIN, type = rw, define = yes;
+ BSS: load = MAIN, type = bss, define = yes;
UPCODE: load = UPLDR, type = ro, define = yes;
UPDATA: load = UPLDR, type = rw, define = yes;
- ZEROPAGE: load = ZP, type = zp;
- EXTZP: load = ZP, type = zp, optional = yes;
- APPZP: load = ZP, type = zp, optional = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
SYMBOLS {
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader
- __BLOCKSIZE__: type = weak, value = 1024; # cart block size
+ __BANK0BLOCKSIZE__: type = weak, value = $0400; # bank 0 cart block size
+ __BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size
__EXEHDR__: type = import;
__BOOTLDR__: type = import;
__DEFDIR__: type = import;
HEADER: file = %O, start = $0000, size = $0040;
BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__;
DIR: file = %O, start = $0000, size = 8;
- RAM: file = %O, define = yes, start = $0200, size = $BE38 - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $0200, size = $BE38 - __STACKSIZE__;
}
SEGMENTS {
- EXEHDR: load = HEADER, type = ro;
- BOOTLDR: load = BOOT, type = ro;
- DIRECTORY: load = DIR, type = ro;
- STARTUP: load = RAM, type = ro, define = yes;
- LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro, define = yes;
- RODATA: load = RAM, type = ro, define = yes;
- DATA: load = RAM, type = rw, define = yes;
- BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
APPZP: load = ZP, type = zp, optional = yes;
+ EXEHDR: load = HEADER, type = ro;
+ BOOTLDR: load = BOOT, type = ro;
+ DIRECTORY: load = DIR, type = ro;
+ STARTUP: load = MAIN, type = ro, define = yes;
+ LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
+ ONCE: load = MAIN, type = ro, define = yes, optional = yes;
+ CODE: load = MAIN, type = ro, define = yes;
+ RODATA: load = MAIN, type = ro, define = yes;
+ DATA: load = MAIN, type = rw, define = yes;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, optional = yes;
HEADER: load = COMBINED, type = ro;
- INIT: load = COMBINED, type = ro, optional = yes;
+ ONCE: load = COMBINED, type = ro, optional = yes;
CODE: load = COMBINED, type = ro;
RODATA: load = COMBINED, type = ro;
DATA: load = COMBINED, type = rw;
# - code
# - rodata
# - data (load)
- ROM0: file = %O, start = $8000, size = $7FF4, fill = yes, define = yes;
+ ROM0: file = %O, start = $8000, size = $7FFA, fill = yes, define = yes;
# Hardware Vectors at End of 2nd 8K ROM
- ROMV: file = %O, start = $FFF6, size = $000C, fill = yes;
+ ROMV: file = %O, start = $FFFA, size = $0006, fill = yes;
# 1 8k CHR Bank
ROM2: file = %O, start = $0000, size = $2000, fill = yes;
RAM: file = "", start = $6000, size = $2000, define = yes;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
HEADER: load = HEADER, type = ro;
- STARTUP: load = ROM0, type = ro, define = yes;
- LOWCODE: load = ROM0, type = ro, optional = yes;
- INIT: load = ROM0, type = ro, define = yes, optional = yes;
- CODE: load = ROM0, type = ro, define = yes;
- RODATA: load = ROM0, type = ro, define = yes;
- DATA: load = ROM0, run = RAM, type = rw, define = yes;
+ STARTUP: load = ROM0, type = ro, define = yes;
+ LOWCODE: load = ROM0, type = ro, optional = yes;
+ ONCE: load = ROM0, type = ro, optional = yes;
+ CODE: load = ROM0, type = ro, define = yes;
+ RODATA: load = ROM0, type = ro, define = yes;
+ DATA: load = ROM0, run = RAM, type = rw, define = yes;
VECTORS: load = ROMV, type = rw;
CHARS: load = ROM2, type = rw;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ BSS: load = RAM, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__STACKSIZE__: type = weak, value = $0800; # 2k stack
}
MEMORY {
- ZP: file = "", define = yes, start = $0000, size = $0001F;
- RAM: file = %O, start = %S, size = $10000 - __STACKSIZE__;
+ ZP: file = "", define = yes, start = $0000, size = $0001F;
+ MAIN: file = %O, start = %S, size = $10000 - __STACKSIZE__;
}
SEGMENTS {
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = rw;
- RODATA: load = RAM, type = rw;
- DATA: load = RAM, type = rw;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ ZEROPAGE: load = ZP, type = zp;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = rw;
+ RODATA: load = MAIN, type = rw;
+ DATA: load = MAIN, type = rw;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
}
MEMORY {
# for size of ZP, see runtime/zeropage.s and c1p/extzp.s
- ZP: file = "", define = yes, start = $0002, size = $001A + $0006;
- HEAD: file = %O, start = $0000, size = $00B6;
- RAM: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
+ ZP: file = "", define = yes, start = $0002, size = $00FE;
+ HEAD: file = %O, start = $0000, size = $00B6;
+ MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
}
SEGMENTS {
- BOOT: load = HEAD, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = rw;
- RODATA: load = RAM, type = rw;
- DATA: load = RAM, type = rw;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ ZEROPAGE: load = ZP, type = zp, optional = yes;
+ BOOT: load = HEAD, type = ro, optional = yes;
+ CODE: load = MAIN, type = rw;
+ RODATA: load = MAIN, type = ro, optional = yes;
+ DATA: load = MAIN, type = rw, optional = yes;
+ BSS: load = MAIN, type = bss, optional = yes, define = yes;
}
}
MEMORY {
# for size of ZP, see runtime/zeropage.s and c1p/extzp.s
- ZP: file = "", define = yes, start = $0002, size = $001A + $0020;
- HEAD: file = %O, start = $0000, size = $00B6;
- RAM: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
+ ZP: file = "", define = yes, start = $0002, size = $001A + $0020;
+ HEAD: file = %O, start = $0000, size = $00B6;
+ MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S;
}
SEGMENTS {
- BOOT: load = HEAD, type = ro, optional = yes;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = rw;
- RODATA: load = RAM, type = rw;
- DATA: load = RAM, type = rw;
- BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = zp, define = yes, optional = yes;
+ BOOT: load = HEAD, type = ro, optional = yes;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = rw;
+ RODATA: load = MAIN, type = rw;
+ DATA: load = MAIN, type = rw;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
# linker config to produce simple NEC PC-Engine cartridge (.pce)
SYMBOLS {
- __STACKSIZE__: type = weak, value = $0300; # 3 pages stack
+ __STACKSIZE__: type = weak, value = $0300; # 3 pages stack
}
MEMORY {
- # FIXME: is this correct? the first 3? bytes cant be used?
- ZP: start = $03, size = $fd, type = rw, define = yes;
+ # FIXME: is this correct? the first 3? bytes cant be used?
+ ZP: file = "", start = $0003, size = $00FD, type = rw, define = yes;
- # reset-bank and hardware vectors
- ROM0: start = $e000, size = $1ff6, file = %O ,fill = yes, define = yes;
- ROMV: start = $fff6, size = $a, file = %O,fill = yes;
+ # reset-bank and hardware vectors
+ ROM0: file = %O, start = $E000, size = $1FF6, fill = yes, define = yes;
+ ROMV: file = %O, start = $FFF6, size = $000A, fill = yes;
- # first RAM page (also contains stack and zeropage)
- RAM: start = $2200, size = $1e00, define = yes;
+ # first RAM page (also contains stack and zeropage)
+ RAM: file = "", start = $2200, size = $1e00, define = yes;
}
SEGMENTS {
- STARTUP: load = ROM0, type = ro, define = yes;
- INIT: load = ROM0, type = ro, define = yes, optional = yes;
- CODE: load = ROM0, type = ro, define = yes;
- RODATA: load = ROM0, type = ro, define = yes;
- DATA: load = ROM0, run= RAM, type = rw, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- VECTORS: load = ROMV, type = rw, define = yes;
- ZEROPAGE: load = ZP, type = zp, define = yes;
- EXTZP: load = ZP, type = zp, define = yes, optional = yes;
- APPZP: load = ZP, type = zp, define = yes, optional = yes;
+ ZEROPAGE: load = ZP, type = zp, define = yes;
+ EXTZP: load = ZP, type = zp, define = yes, optional = yes;
+ APPZP: load = ZP, type = zp, define = yes, optional = yes;
+ STARTUP: load = ROM0, type = ro, define = yes;
+ ONCE: load = ROM0, type = ro, optional = yes;
+ CODE: load = ROM0, type = ro, define = yes;
+ RODATA: load = ROM0, type = ro, define = yes;
+ DATA: load = ROM0, run = RAM, type = rw, define = yes;
+ BSS: load = RAM, type = bss, define = yes;
+ VECTORS: load = ROMV, type = rw, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
RAM: file = %O, start = $040D, size = $7BF3 - __STACKSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
+ LOWCODE: load = RAM, type = ro, optional = yes;
+ ONCE: load = RAM, type = ro, optional = yes;
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ INIT: load = RAM, type = bss;
+ BSS: load = RAM, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = $0FFF, size = $0002;
HEADER: file = %O, start = $1001, size = $000C;
- RAM: file = %O, define = yes, start = $100D, size = $ECF3 - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $100D, size = $ECF3 - __STACKSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: 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 = bss;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__STACKSIZE__: type = weak, value = $0800; # 2k stack
}
MEMORY {
- ZP: file = "", start = $0000, size = $001A;
- HEADER: file = %O, start = $0000, size = $0001;
- RAM: file = %O, define = yes, start = $0200, size = $FDF0 - __STACKSIZE__;
+ ZP: file = "", start = $0000, size = $001A;
+ HEADER: file = %O, start = $0000, size = $0001;
+ MAIN: file = %O, define = yes, start = $0200, size = $FDF0 - __STACKSIZE__;
}
SEGMENTS {
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ ZEROPAGE: load = ZP, type = zp;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
__STACKSIZE__: type = weak, value = $0800; # 2k stack
}
MEMORY {
- ZP: file = "", start = $0000, size = $001A;
- HEADER: file = %O, start = $0000, size = $0001;
- RAM: file = %O, define = yes, start = $0200, size = $FDF0 - __STACKSIZE__;
+ ZP: file = "", start = $0000, size = $001A;
+ HEADER: file = %O, start = $0000, size = $0001;
+ MAIN: file = %O, define = yes, start = $0200, size = $FDF0 - __STACKSIZE__;
}
SEGMENTS {
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ ZEROPAGE: load = ZP, type = zp;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ROM: file = %O, start = $c000, size = $4000, fill = yes, fillval = $FF;
}
SEGMENTS {
- LOWCODE: load = ROM, type = ro, optional = yes;
- INIT: load = ROM, type = ro, define = yes, optional = yes;
+ LOWCODE: load = ROM, type = ro, optional = yes;
+ ONCE: load = ROM, type = ro, optional = yes;
CODE: load = ROM, type = ro;
BANK1: load = BANKROM1, type = ro;
BANK2: load = BANKROM2, type = ro;
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;
- BSS: load = RAM, type = bss, define = yes;
- VECTOR: load = ROM, type = ro, offset = $3FFA;
+ ZEROPAGE: load = RAM, type = bss, define = yes;
+ DATA: load = RAM, type = bss, define = yes, offset = $0200;
+ BSS: load = RAM, type = bss, define = yes;
+ VECTOR: load = ROM, type = ro, offset = $3FFA;
}
ROM: file = %O, start = $C000, size = $4000, fill = yes, fillval = $ff, define=yes;
}
SEGMENTS {
- LOWCODE: load = ROM, type = ro, optional = yes;
- INIT: load = ROM, type = ro, define = yes, optional = yes;
- 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;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp, define = yes;
+ ZEROPAGE: load = ZP, type = zp, define = yes;
+ LOWCODE: load = ROM, type = ro, optional = yes;
+ ONCE: load = ROM, type = ro, optional = yes;
+ 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;
+ BSS: load = RAM, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ROM: file = %O, start = $C000, size = $4000, fill = yes, fillval = $FF;
}
SEGMENTS {
- LOWCODE: load = ROM, type = ro, optional = yes;
- INIT: load = ROM, type = ro, define = yes, optional = yes;
+ LOWCODE: load = ROM, type = ro, optional = yes;
+ ONCE: load = ROM, type = ro, optional = yes;
CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro;
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;
- BSS: load = RAM, type = bss, define = yes;
- VECTOR: load = ROM, type = ro, offset = $3FFA;
+ ZEROPAGE: load = RAM, type = bss, define = yes;
+ DATA: load = RAM, type = bss, define = yes, offset = $0200;
+ BSS: load = RAM, type = bss, define = yes;
+ VECTOR: load = ROM, type = ro, offset = $3FFA;
}
# make sure the halves are mirrored in the 64kbyte cartridge image
# or reset from code >0xc000 and switch bank to the 3rd bank
+SYMBOLS {
+ __STACKSIZE__: type = weak, value = $0100; # 1 page stack
+}
MEMORY {
ZP: file = "", start = $0000, size = $0100;
CPUSTACK: file = "", start = $0100, size = $0100;
- RAM: file = "", start = $0200, size = $1E00, define = yes;
+ RAM: file = "", start = $0200, size = $1E00 - __STACKSIZE__;
VRAM: file = "", start = $4000, size = $2000;
ROM: file = %O, start = $8000, size = $8000, fill = yes, fillval = $FF, define = yes;
}
SEGMENTS {
- LOWCODE: load = ROM, type = ro, optional = yes;
- INIT: load = ROM, type = ro, define = yes, optional = yes;
- 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;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp, define = yes;
+ ZEROPAGE: load = ZP, type = zp, define = yes;
+ LOWCODE: load = ROM, type = ro, optional = yes;
+ ONCE: load = ROM, type = ro, optional = yes;
+ 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;
+ BSS: load = RAM, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = $11FF, size = $0002;
HEADER: file = %O, start = $1201, size = $000C;
- RAM: file = %O, define = yes, start = $120D, size = $6DF3 - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $120D, size = $6DF3 - __STACKSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: 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 = bss;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = $0FFF, size = $0002;
HEADER: file = %O, start = $1001, size = $000C;
- RAM: file = %O, define = yes, start = $100D, size = $0DF3 - __STACKSIZE__;
+ MAIN: file = %O, define = yes, start = $100D, size = $0DF3 - __STACKSIZE__;
}
SEGMENTS {
+ ZEROPAGE: load = ZP, type = zp;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- INIT: load = RAM, type = ro, define = yes, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- INITBSS: load = RAM, type = bss;
- BSS: load = RAM, type = bss, define = yes;
- ZEROPAGE: load = ZP, type = zp;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ ONCE: 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 = bss;
+ BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
- segment = INIT;
+ segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
htmldir = $(prefix)/share/doc/cc65$(DESTPACKAGE_SUFFIX)/html
infodir = $(prefix)/share/info
-all mostlyclean:
-
ifdef CMD_EXE
-clean install zip doc:
+doc clean install zip:
else # CMD_EXE
INSTALL = install
-clean:
- $(RM) -r ../html ../info
-
-install:
- $(if $(prefix),,$(error variable `prefix' must be set))
-ifeq ($(wildcard ../html),../html)
- $(INSTALL) -d $(DESTDIR)$(htmldir)
- $(INSTALL) -m644 ../html/*.* $(DESTDIR)$(htmldir)
-endif
-ifeq ($(wildcard ../info),../info)
- $(INSTALL) -d $(DESTDIR)$(infodir)
- $(INSTALL) -m644 ../info/*.* $(DESTDIR)$(infodir)
-endif
-
-zip:
- @cd .. && zip cc65 html/*.*
-
doc: html info
html: $(addprefix ../html/,$(SGMLS:.sgml=.html) doc.css doc.png)
../info/%.info: %.sgml | ../info
@cd ../info && linuxdoc -B info ../doc/$<
+clean:
+ $(RM) -r ../html ../info
+
+install:
+ $(if $(prefix),,$(error variable `prefix' must be set))
+ifeq ($(wildcard ../html),../html)
+ $(INSTALL) -d $(DESTDIR)$(htmldir)
+ $(INSTALL) -m0644 ../html/*.* $(DESTDIR)$(htmldir)
+endif
+ifeq ($(wildcard ../info),../info)
+ $(INSTALL) -d $(DESTDIR)$(infodir)
+ $(INSTALL) -m0644 ../info/*.* $(DESTDIR)$(infodir)
+endif
+
+zip:
+ifneq "$(wildcard ../html)" ""
+ @cd .. && zip cc65 html/*.*
+endif
+
endif # CMD_EXE
+
+all mostlyclean:
Enabling the Language Card allows to use it as additional memory for cc65
generated code. However code is never automatically placed there. Rather code
needs to be explicitly placed in the Language Card either per file by compiling
-with <tt/--code-name HIGHCODE/ or per function by enclosing in <tt/#pragma
-code-name (push, "HIGHCODE")/ and <tt/#pragma code-name (pop)/. In either case the
-cc65 runtime system takes care of actually moving the code into the Language
-Card.
+with <tt/--code-name LC/ or per function by enclosing in <tt/#pragma code-name
+(push, "LC")/ and <tt/#pragma code-name (pop)/. In either case the cc65 runtime
+system takes care of actually moving the code into the Language Card.
The amount of memory available in the Language Card for generated code depends
-on the chosen <ref id="link-configs" name="linker configuration">.
+on the <ref id="link-configs" name="linker configuration"> parameters. There are
+several usefull settings:
+
+<descrip>
+
+ <tag>LC address: $D400, LC size: $C00</tag>
+ For plain vanilla ProDOS 8 which doesn't actually use the Language Card bank 2
+ memory from $D400 to $DFFF. This is the default setting.
+
+ <tag>LC address: $D000, LC size: $1000</tag>
+ For ProDOS 8 together with the function <tt/rebootafterexit()/. If a program
+ doesn't quit to the ProDOS 8 dispatcher but rather reboots the machine after
+ exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank
+ 2 at all.
+
+ <tag>LC address: $D000, LC size: $3000</tag>
+ For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all.
+
+</descrip><p>
are used via <tt/-t apple2 -C <configfile>/.
-<sect1>default config file (<tt/apple2.cfg/)<p>
+<sect1>default config file (<tt/apple2.cfg/)<label id="apple-def-cfg"><p>
-Default configuration optimized for a binary program running on ProDOS 8 with
-BASIC.SYSTEM. A plain vanilla ProDOS 8 doesn't actually use the Language Card
-bank 2 memory from $D400 to $DFFF.
+Default configuration for a binary program.
-<descrip>
-
- <tag><tt/RAM:/ Main memory area</tag>
- From $803 to $95FF (35.5 KB)
+Parameters:
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D400 to $DFFF (3 KB)
+<descrip>
<tag><tt/STARTADDRESS:/ Program start address</tag>
- Variable (default: $803)
-
- <tag><tt/HEADER:/ Binary file header</tag>
- DOS 3.3 header (address and length)
-
-</descrip><p>
-
+ Default: $803. Use <tt/-S <addr>/ to set a different start address.
-<sect1><tt/apple2-dos33.cfg/<p>
+ <tag><tt/__EXEHDR__:/ Executable file header</tag>
+ Default: DOS 3.3 header (address and length). Use <tt/-D __EXEHDR__=0/ to omit
+ the header.
-Configuration optimized for a binary program running on DOS 3.3. A plain
-vanilla DOS 3.3 doesn't make use of the Language Card at all.
+ <tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
+ Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
+ stack size.
-<descrip>
-
- <tag><tt/RAM:/ Main memory area</tag>
- From $803 to $95FF (35.5 KB)
+ <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag>
+ Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different
+ highest usable address.
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D000 to $FFFF (12 KB)
-
- <tag><tt/STARTADDRESS:/ Program start address</tag>
- Variable (default: $803)
+ <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
+ Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
+ code address.
- <tag><tt/HEADER:/ Binary file header</tag>
- DOS 3.3 header (address and length)
+ <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
+ Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
+ code size.
</descrip><p>
<sect1><tt/apple2-system.cfg/<label id="apple-sys-cfg"><p>
-Configuration for a system program running on ProDOS 8.
+Configuration for a system program running on ProDOS 8 and using the memory from
+$2000 to $BEFF.
-<descrip>
+Parameters:
- <tag><tt/RAM:/ Main memory area</tag>
- From $2000 to $BEFF (39.75 KB)
+<descrip>
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D400 to $DFFF (3 KB)
+ <tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
+ Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
+ stack size.
- <tag><tt/STARTADDRESS:/ Program start address</tag>
- Fixed ($2000)
+ <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
+ Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
+ code address.
- <tag><tt/HEADER:/ Binary file header</tag>
- None
+ <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
+ Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
+ code size.
</descrip><p>
-<sect1><tt/apple2-loader.cfg/<label id="apple-load-cfg"><p>
+<sect1><tt/apple2-overlay.cfg/<p>
-Configuration optimized for a binary program running on ProDOS 8 without
-BASIC.SYSTEM. Intended to be used with <bf/LOADER.SYSTEM - an
-Apple ][ ProDOS 8 loader for cc65 programs/, which is available
-in the cc65 User Contributions section.
+Configuration for overlay programs with the up to nine overlays. The overlay files
+don't include the DOS 3.3 header. See <tt>samples/overlaydemo.c</tt> for more
+information on overlays.
-A program loaded by LOADER.SYSTEM works like a ProDOS 8 system program but
-isn't tied to the start address $2000. Thus with the default start
-address $800 the main memory area is increased by 6 KB.
+Parameters:
<descrip>
- <tag><tt/RAM:/ Main memory area</tag>
- From $800 to $BEFF (45.75 KB)
+ <tag><tt/STARTADDRESS:/ Program start address</tag>
+ Default: $803. Use <tt/-S <addr>/ to set a different start address.
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D400 to $DFFF (3 KB)
+ <tag><tt/__EXEHDR__:/ Executable file header</tag>
+ Default: DOS 3.3 header (address and length). Use <tt/-D __EXEHDR__=0/ to omit
+ the header.
- <tag><tt/STARTADDRESS:/ Program start address</tag>
- Variable (default: $800)
+ <tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
+ Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
+ stack size.
- <tag><tt/HEADER:/ Binary file header</tag>
- DOS 3.3 header (address and length)
+ <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag>
+ Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different
+ highest usable address.
-</descrip><p>
+ <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
+ Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
+ code address.
+ <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
+ Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
+ code size.
-<sect1><tt/apple2-reboot.cfg/<p>
+ <tag><tt/__OVERLAYSIZE__:/ Size of code in the overlays</tag>
+ Default: $1000. Use <tt/-D __OVERLAYSIZE__=<size>/ to set a different
+ code size.
-Configuration optimized for a binary program running on ProDOS 8 without
-BASIC.SYSTEM. Intended to be used with <bf/LOADER.SYSTEM - an
-Apple ][ ProDOS 8 loader for cc65 programs/ (see above) together
-with the function <tt/rebootafterexit()/.
+</descrip><p>
-If a ProDOS 8 system program doesn't quit to the ProDOS 8 dispatcher but rather
-reboots the machine after exit then a plain vanilla ProDOS 8 doesn't make use of
-the Language Card bank 2 at all.
-This setup makes nearly 50 KB available to a cc65 program - on a 64 KB machine!
+<sect1><tt/apple2-asm.cfg/<p>
-<descrip>
+Configuration for a assembler programs which don't need a special setup.
- <tag><tt/RAM:/ Main memory area</tag>
- From $800 to $BEFF (45.75 KB)
+Parameters:
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D000 to $DFFF (4 KB)
+<descrip>
<tag><tt/STARTADDRESS:/ Program start address</tag>
- Variable (default: $800)
+ Default: $803. Use <tt/-S <addr>/ to set a different start address.
- <tag><tt/HEADER:/ Binary file header</tag>
- DOS 3.3 header (address and length)
+ <tag><tt/__EXEHDR__:/ Executable file header</tag>
+ Default: No header. Use <tt/-u __EXEHDR__ apple2.lib/ to add a DOS 3.3 header
+ (address and length).
</descrip><p>
The easiest (and for really large programs in fact the only) way to have a cc65
program use the memory from $800 to $2000 is to link it as binary
-(as opposed to system) program using the linker configuration
-<ref id="apple-load-cfg" name="apple2-loader.cfg"> with start address
-$803 and load it with the targetutil LOADER.SYSTEM. The program then works
-like a system program (i.e. quits to the ProDOS dispatcher).
+(as opposed to system) program using the default linker configuration
+<ref id="apple-def-cfg" name="apple2.cfg"> with <tt/__HIMEM__/ set to $BF00
+and load it with the LOADER.SYSTEM utility. The program then works like a system
+program (i.e. quits to the ProDOS dispatcher).
Using LOADER.SYSTEM is as simple as copying it to the ProDOS 8 directory of the
program to load under name <program>.SYSTEM as a system program. For
<tag><tt/a2.hi.tgi (a2_hi_tgi)/</tag>
This driver features a resolution of 280×192 with 8 colors and two
hires pages. Note that programs using this driver will have to be linked
- with <tt/--start-addr $4000/ to reserve the first hires page or with
- <tt/--start-addr $6000/ to reserve both hires pages.
+ with <tt/-S $4000/ to reserve the first hires page or with <tt/-S $6000/
+ to reserve both hires pages.
The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The
function doesn't clear the corresponding area at the bottom of the screen.
for an AppleMouse II Card compatible firmware. The default bounding
box is [0..279,0..191].
- Programs using this driver will have to be linked with <tt/--start-addr $4000/
+ Programs using this driver will have to be linked with <tt/-S $4000/
to reserve the first hires page if they are intended to run on an
Apple ][ (in contrast to an Apple //e) because the
AppleMouse II Card firmware writes to the hires page when initializing
The Apple ][ has no color text mode. Therefore the functions textcolor(),
bgcolor() and bordercolor() have no effect.
- <tag/Cursor/
- The Apple ][ has no hardware cursor. Therefore the function cursor() has
- no effect.
-
</descrip><p>
Enabling the Language Card allows to use it as additional memory for cc65
generated code. However code is never automatically placed there. Rather code
needs to be explicitly placed in the Language Card either per file by compiling
-with <tt/--code-name HIGHCODE/ or per function by enclosing in <tt/#pragma
-code-name (push, "HIGHCODE")/ and <tt/#pragma code-name (pop)/. In either case the
-cc65 runtime system takes care of actually moving the code into the Language
-Card.
+with <tt/--code-name LC/ or per function by enclosing in <tt/#pragma code-name
+(push, "LC")/ and <tt/#pragma code-name (pop)/. In either case the cc65 runtime
+system takes care of actually moving the code into the Language Card.
The amount of memory available in the Language Card for generated code depends
-on the chosen <ref id="link-configs" name="linker configuration">.
+on the <ref id="link-configs" name="linker configuration"> parameters. There are
+several usefull settings:
+
+<descrip>
+
+ <tag>LC address: $D400, LC size: $C00</tag>
+ For plain vanilla ProDOS 8 which doesn't actually use the Language Card bank 2
+ memory from $D400 to $DFFF. This is the default setting.
+
+ <tag>LC address: $D000, LC size: $1000</tag>
+ For ProDOS 8 together with the function <tt/rebootafterexit()/. If a program
+ doesn't quit to the ProDOS 8 dispatcher but rather reboots the machine after
+ exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank
+ 2 at all.
+
+ <tag>LC address: $D000, LC size: $3000</tag>
+ For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all.
+
+</descrip><p>
are used via <tt/-t apple2enh -C <configfile>/.
-<sect1>default config file (<tt/apple2enh.cfg/)<p>
+<sect1>default config file (<tt/apple2enh.cfg/)<label id="apple-def-cfg"><p>
-Default configuration optimized for a binary program running on ProDOS 8 with
-BASIC.SYSTEM. A plain vanilla ProDOS 8 doesn't actually use the Language Card
-bank 2 memory from $D400 to $DFFF.
+Default configuration for a binary program.
-<descrip>
+Parameters:
- <tag><tt/RAM:/ Main memory area</tag>
- From $803 to $95FF (35.5 KB)
-
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D400 to $DFFF (3 KB)
+<descrip>
<tag><tt/STARTADDRESS:/ Program start address</tag>
- Variable (default: $803)
-
- <tag><tt/HEADER:/ Binary file header</tag>
- DOS 3.3 header (address and length)
-
-</descrip><p>
-
-
-<sect1><tt/apple2enh-dos33.cfg/<p>
+ Default: $803. Use <tt/-S <addr>/ to set a different start address.
-Configuration optimized for a binary program running on DOS 3.3. A plain
-vanilla DOS 3.3 doesn't make use of the Language Card at all.
+ <tag><tt/__EXEHDR__:/ Executable file header</tag>
+ Default: DOS 3.3 header (address and length). Use <tt/-D __EXEHDR__=0/ to omit
+ the header.
-<descrip>
-
- <tag><tt/RAM:/ Main memory area</tag>
- From $803 to $95FF (35.5 KB)
+ <tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
+ Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
+ stack size.
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D000 to $FFFF (12 KB)
+ <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag>
+ Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different
+ highest usable address.
- <tag><tt/STARTADDRESS:/ Program start address</tag>
- Variable (default: $803)
+ <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
+ Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
+ code address.
- <tag><tt/HEADER:/ Binary file header</tag>
- DOS 3.3 header (address and length)
+ <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
+ Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
+ code size.
</descrip><p>
<sect1><tt/apple2enh-system.cfg/<label id="apple-sys-cfg"><p>
-Configuration for a system program running on ProDOS 8.
+Configuration for a system program running on ProDOS 8 and using the memory from
+$2000 to $BEFF.
-<descrip>
+Parameters:
- <tag><tt/RAM:/ Main memory area</tag>
- From $2000 to $BEFF (39.75 KB)
+<descrip>
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D400 to $DFFF (3 KB)
+ <tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
+ Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
+ stack size.
- <tag><tt/STARTADDRESS:/ Program start address</tag>
- Fixed ($2000)
+ <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
+ Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
+ code address.
- <tag><tt/HEADER:/ Binary file header</tag>
- None
+ <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
+ Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
+ code size.
</descrip><p>
-<sect1><tt/apple2enh-loader.cfg/<label id="apple-load-cfg"><p>
+<sect1><tt/apple2enh-overlay.cfg/<p>
-Configuration optimized for a binary program running on ProDOS 8 without
-BASIC.SYSTEM. Intended to be used with <bf/LOADER.SYSTEM - an
-Apple ][ ProDOS 8 loader for cc65 programs/, which is available
-in the cc65 User Contributions section.
+Configuration for overlay programs with the up to nine overlays. The overlay files
+don't include the DOS 3.3 header. See <tt>samples/overlaydemo.c</tt> for more
+information on overlays.
-A program loaded by LOADER.SYSTEM works like a ProDOS 8 system program but
-isn't tied to the start address $2000. Thus with the default start
-address $800 the main memory area is increased by 6 KB.
+Parameters:
<descrip>
- <tag><tt/RAM:/ Main memory area</tag>
- From $800 to $BEFF (45.75 KB)
+ <tag><tt/STARTADDRESS:/ Program start address</tag>
+ Default: $803. Use <tt/-S <addr>/ to set a different start address.
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D400 to $DFFF (3 KB)
+ <tag><tt/__EXEHDR__:/ Executable file header</tag>
+ Default: DOS 3.3 header (address and length). Use <tt/-D __EXEHDR__=0/ to omit
+ the header.
- <tag><tt/STARTADDRESS:/ Program start address</tag>
- Variable (default: $800)
+ <tag><tt/__STACKSIZE__:/ C runtime stack size</tag>
+ Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different
+ stack size.
- <tag><tt/HEADER:/ Binary file header</tag>
- DOS 3.3 header (address and length)
+ <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag>
+ Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different
+ highest usable address.
-</descrip><p>
+ <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag>
+ Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different
+ code address.
+ <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag>
+ Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different
+ code size.
-<sect1><tt/apple2enh-reboot.cfg/<p>
+ <tag><tt/__OVERLAYSIZE__:/ Size of code in the overlays</tag>
+ Default: $1000. Use <tt/-D __OVERLAYSIZE__=<size>/ to set a different
+ code size.
-Configuration optimized for a binary program running on ProDOS 8 without
-BASIC.SYSTEM. Intended to be used with <bf/LOADER.SYSTEM - an
-Apple ][ ProDOS 8 loader for cc65 programs/ (see above) together
-with the function <tt/rebootafterexit()/.
+</descrip><p>
-If a ProDOS 8 system program doesn't quit to the ProDOS 8 dispatcher but rather
-reboots the machine after exit then a plain vanilla ProDOS 8 doesn't make use of
-the Language Card bank 2 at all.
-This setup makes nearly 50 KB available to a cc65 program - on a 64 KB machine!
+<sect1><tt/apple2enh-asm.cfg/<p>
-<descrip>
+Configuration for a assembler programs which don't need a special setup.
- <tag><tt/RAM:/ Main memory area</tag>
- From $800 to $BEFF (45.75 KB)
+Parameters:
- <tag><tt/LC:/ Language Card memory area</tag>
- From $D000 to $DFFF (4 KB)
+<descrip>
<tag><tt/STARTADDRESS:/ Program start address</tag>
- Variable (default: $800)
+ Default: $803. Use <tt/-S <addr>/ to set a different start address.
- <tag><tt/HEADER:/ Binary file header</tag>
- DOS 3.3 header (address and length)
+ <tag><tt/__EXEHDR__:/ Executable file header</tag>
+ Default: No header. Use <tt/-u __EXEHDR__ apple2enh.lib/ to add a DOS 3.3 header
+ (address and length).
</descrip><p>
The easiest (and for really large programs in fact the only) way to have a cc65
program use the memory from $800 to $2000 is to link it as binary
-(as opposed to system) program using the linker configuration
-<ref id="apple-load-cfg" name="apple2enh-loader.cfg"> with start address
-$803 and load it with the targetutil LOADER.SYSTEM. The program then works
-like a system program (i.e. quits to the ProDOS dispatcher).
+(as opposed to system) program using the default linker configuration
+<ref id="apple-def-cfg" name="apple2enh.cfg"> with <tt/__HIMEM__/set to $BF00
+and load it with the LOADER.SYSTEM utility. The program then works like a system
+program (i.e. quits to the ProDOS dispatcher).
Using LOADER.SYSTEM is as simple as copying it to the ProDOS 8 directory of the
program to load under name <program>.SYSTEM as a system program. For
in memory the primary benefit of <tt/apple2enh-iobuf-0800.o/ is a reduction in code
size - and thus program file size - of more than 1400 bytes.
-Using <tt/apple2enh-iobuf-0800.o/ is as simple as placing it on the linker command
+Using <tt/apple2enh-iobuf-0800.o/ is as simple as placing it on the linker command
line like this:
<tscreen><verb>
<tag><tt/a2e.hi.tgi (a2e_hi_tgi)/</tag>
This driver features a resolution of 280×192 with 8 colors and two
hires pages. Note that programs using this driver will have to be linked
- with <tt/--start-addr $4000/ to reserve the first hires page or with
- <tt/--start-addr $6000/ to reserve both hires pages.
+ with <tt/-S $4000/ to reserve the first hires page or with <tt/-S $6000/
+ to reserve both hires pages.
Note that the second hires page is only available if the text display is not in
80 column mode. This can be asserted by calling <tt/videomode (VIDEOMODE_40COL);/
<tag><tt/a2e.auxmem.emd (a2e_auxmem_emd)/</tag>
Gives access to 47.5 KB RAM (190 pages of 256 bytes each) on an Extended
80-Column Text Card.
-
+
Note that this driver doesn't check for the actual existence of the memory
and that it doesn't check for ProDOS 8 RAM disk content!
'Failed to alloc interrupt' on program startup. This implicitly means that
<tt/a2e.stdmou.mou/ and <tt/a2e.ssc.ser/ are not functional as they depend on
interrupts.
-
+
</descrip><p>
The enhanced Apple //e has no color text mode. Therefore the functions
textcolor(), bgcolor() and bordercolor() have no effect.
- <tag/Cursor/
- The enhanced Apple //e has no hardware cursor. Therefore the function
- cursor() has no effect.
-
</descrip><p>
<tag/Drive ID/
The function <url url="dio.html#s1" name="dio_open()"> has the single
parameter <tt/device/ to identify the device to be opened. Therefore an
- Apple II slot and drive pair is mapped to that <tt/drive_id/ according
+ Apple II slot and drive pair is mapped to that <tt/device/ according
to the formula
<tscreen>
($58).
<tag/Stack/
- The C runtime stack is located at end of the RAM memory area ($CFFF)
+ The C runtime stack is located at end of the MAIN memory area ($CFFF)
and grows downwards.
<tag/Heap/
The size of a cassette boot file is restricted to 32K. Larger programs
would need to be split in more parts and the parts to be loaded manually.
-To write the generated file to a cassette, a utility to run
-on an Atari is provided in the <tt/targetutil/ directory (<tt/w2cas.com/).
+To write the generated file to a cassette, a utility (<tt/w2cas.com/) to run
+on an Atari is provided in the <tt/util/ directory of <tt/atari/ target dir.
<sect1><tt/atarixl/ config files<p>
<item>_getcolor
<item>_getdefdev
<item>_graphics
+<item>_is_cmdline_dos
<item>_rest_vecs
<item>_save_vecs
<item>_scroll
</descrip><p>
+<sect1>Character mapping<p>
+
+The Atari has two representations for characters:
+<enum>
+<item> ATASCII is character mapping which is similar to ASCII and used
+by the CIO system of the OS. This is the default mapping of cc65 when
+producing code for the atari target.
+<item> The internal/screen mapping represents the real value of the
+screen ram when showing a character.
+</enum>
+
+For direct memory access (simplicity and speed) enabling the internal
+mapping can be useful. This can be achieved by including the
+"<tt/atari_screen_charmap.h/" header.
+
+A word of caution: Since the <tt/0x00/ character has to be mapped in an
+incompatible way to the C-standard, the usage of string functions in
+conjunction with internal character mapped strings delivers unexpected
+results regarding the string length. The end of strings are detected where
+you may not expect them (too early or (much) too late). Internal mapped
+strings typically support the "<tt/mem...()/" functions.
+
+<em>For assembler sources the macro "<tt/scrcode/" from the "<tt/atari.mac/"
+package delivers the same feature.</em>
+
+You can switch back to the ATASCII mapping by including
+"<tt/atari_atascii_charmap.h/".
+
+A final note: Since cc65 has currently some difficulties with string merging
+under different mappings, defining remapped strings works only flawlessly
+with static array initialization:
+
+<verb>
+#include <atari\_screen\_charmap.h>
+char pcScreenMappingString[] = "Hello Atari!";
+
+#include <atari_atascii_charmap.h>
+char pcAtasciiMappingString[] = "Hello Atari!";
+</verb>
+
+delivers correct results, while
+
+<verb>
+#include <atari_screen_charmap.h>
+char* pcScreenMappingString = "Hello Atari!";
+
+#include <atari_atascii_charmap.h>
+char* pcAtasciiMappingString = "Hello Atari!";
+</verb>
+
+does not.
+
<sect>Loadable drivers<p>
<item>main program&nl;
This load chunk is loaded at the selected program start address (default $2000) and
contains all of the code and data of the program.&nl;
-The contents of this chunk come from the RAM memory area of the linker config file.
+The contents of this chunk come from the MAIN memory area of the linker config file.
</enum>
<p>
The main problem is that the EXE header generated by the cc65 runtime
lib is wrong. It defines a single load chunk with the sizes/addresses
-of the STARTUP, LOWCODE, INIT, CODE, RODATA, and DATA segments, in
+of the STARTUP, LOWCODE, ONCE, CODE, RODATA, and DATA segments, in
fact, the whole user program (we're disregarding the "system check"
load chunk here).
<p>
NEXEHDR: load = FSTHDR, type = ro; # first load chunk
STARTUP: load = RAMLO, type = ro, define = yes;
LOWCODE: load = RAMLO, type = ro, define = yes, optional = yes;
- INIT: load = RAMLO, type = ro, optional = yes;
+ ONCE: load = RAMLO, type = ro, optional = yes;
CODE: load = RAMLO, type = ro, define = yes;
CHKHDR: load = SECHDR, type = ro; # second load chunk
AUTOSTRT: load = RAM, type = ro; # defines program entry point
}
FEATURES {
- CONDES: segment = RODATA,
+ CONDES: segment = ONCE,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
<p>
The newly added NEXEHDR segment defines the correct chunk header for the
first intended load chunk. It
-puts the STARTUP, LOWCODE, INIT, and CODE segments, which are the
+puts the STARTUP, LOWCODE, ONCE, and CODE segments, which are the
segments containing only code, into load chunk #1 (RAMLO memory area).
<p>
The header for the second load chunk comes from the new CHKHDR
<sect2>Low data and high code example<p>
-Goal: Put RODATA and DATA into low memory and STARTUP, LOWCODE, INIT,
+Goal: Put RODATA and DATA into low memory and STARTUP, LOWCODE, ONCE,
CODE, BSS, ZPSAVE into high memory (split2.cfg):
<tscreen><verb>
CHKHDR: load = SECHDR, type = ro; # second load chunk
STARTUP: load = RAM, type = ro, define = yes;
- INIT: load = RAM, type = ro, optional = yes;
+ ONCE: load = RAM, type = ro, optional = yes;
CODE: load = RAM, type = ro, define = yes;
BSS: load = RAM, type = bss, define = yes;
AUTOSTRT: load = RAM, type = ro; # defines program entry point
}
FEATURES {
- CONDES: segment = RODATA,
+ CONDES: segment = ONCE,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
--- /dev/null
+<!doctype linuxdoc system>
+
+<article>
+
+<title>Atari 2600 specific information for cc65
+<author>
+<url url="mailto:contact@florentflament.com" name="Florent Flament"><newline>
+<date>2017-01-11
+
+<abstract>
+An overview over the Atari 2600 runtime system as it is implemented
+for the cc65 C compiler.
+</abstract>
+
+<!-- Table of contents -->
+<toc>
+
+<!-- Begin the document -->
+
+<sect>Overview<p>
+
+This file contains an overview of the Atari 2600 runtime system as it
+comes with the cc65 C compiler. It describes the memory layout, Atari
+2600 specific header files and any pitfalls specific to that platform.
+
+<sect>Binary format<p>
+
+The default binary output format generated by the linker for the Atari
+2600 target is a 4K cartridge image.
+
+<sect>Memory layout<p>
+
+cc65 generated programs with the default setup can use RAM from
+$0080 to $00FF - __STACKSIZE__, where __STACKSIZE__ is
+the size of the system stack with a default value of 16 bytes. The
+size of the system stack can be customized by defining the
+__STACKSIZE__ linker variable.
+
+Special locations:
+
+<descrip>
+ <tag/Stack/ The C runtime stack is located at $00FF -
+ __STACKSIZE__ and growing downwards.
+
+ <tag/Heap/ The C heap is located at $0080 and grows upwards.
+
+</descrip><p>
+
+<sect>Start-up condition<p>
+
+When powered-up, the Atari 2600 TIA registers contain random
+values. During the initialization phase, the start-up code needs to
+initialize the TIA registers to sound values (or else the console has
+an unpredictable behavior). In this implementation, zeros are written
+to all of TIA registers during the start-up phase.
+
+Note that RIOT registers (mostly timers) are left uninitialized, as
+they don't have any consequence on the console behavior.
+
+<sect>Platform specific header files<p>
+
+Programs containing Atari 2600 specific code may use the
+<tt/atari2600.h/ header file.
+
+The following pseudo variables declared in the <tt/atari2600.h/ header
+file allow access to the Atari 2600 TIA & RIOT chips registers.
+
+<descrip>
+
+ <tag><tt/TIA/</tag> The <tt/TIA/ structure allows read/write access
+ to the Atari 2600 TIA chip registers. See the <tt/_tia.h/ header
+ file located in the include directory for the declaration of the
+ structure. Also refer to the Stella Programmer's Guide by Steve
+ Wright for a detailed description of the chip and its registers.
+
+ <tag><tt/RIOT/</tag> The <tt/RIOT/ structure allows read/write
+ access to the Atari 2600 RIOT chip registers. See the
+ <tt/_riot.h/ header file located in the include directory for the
+ declaration of the structure. Also refer to the Stella Programmer's
+ Guide by Steve Wright for a detailed description of the chip and its
+ registers.
+
+</descrip><p>
+
+
+<sect>Loadable drivers<p>
+
+There are no drivers for the Atari 2600.
+
+
+<sect>Limitations<p>
+
+TBD
+
+
+<sect>Other hints<p>
+
+One may write a custom linker configuration file to tune the memory
+layout of a program. See the <tt/atari2600.cfg/ file in the cfg
+directory as a starting point.
+
+
+<sect>License<p>
+
+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:
+
+<enum>
+<item> 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.
+<item> Altered source versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+<item> This notice may not be removed or altered from any source
+ distribution.
+</enum>
+
+</article>
<descrip>
+ <tag><tt/c128-efnram.emd (c128_efnram_emd)/</tag>
+ Extended memory driver for the C128 External Function RAM.
+ Written and contributed by Marco van den Heuvel.
+
<tag><tt/c128-georam.emd (c128_georam_emd)/</tag>
A driver for the GeoRam cartridge. The driver will always assume 2048 pages
of 256 bytes each. There are no checks, so if your program knows better,
just go ahead.
+ <tag><tt/c128-ifnram.emd (c128_ifnram_emd)/</tag>
+ Extended memory driver for the C128 Internal Function RAM.
+ Written and contributed by Marco van den Heuvel.
+
<tag><tt/c128-ram.emd (c128_ram_emd)/</tag>
An extended memory driver for the RAM in page 1. The common memory area is
excluded, so this driver supports 251 pages of 256 bytes each.
<tag><tt/c128-ptvjoy.joy (c128_ptvjoy_joy)/</tag>
Driver for the Protovision 4-player adapter originally written by Groepaz
for the C64, and converted for the C128 by Uz. See <url
- url="http://www.protovision-online.de/hardw/hardwstart.htm"> for prices and
- building instructions. Up to four joysticks are supported.
+ url="http://www.protovision-online.de/hardw/4_player.php?language=en"
+ name="Protovision shop"> for prices and building instructions. Up to four
+ joysticks are supported.
<tag><tt/c128-stdjoy.joy (c128_stdjoy_joy)/</tag>
Supports up to two joysticks connected to the standard joysticks ports of
<article>
<title>Commodore 64-specific information for cc65
-<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
-<date>2014-04-14
+<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"><newline>
+<url url="mailto:greg.king5@verizon.net" name="Greg King">
+<date>2017-01-18
<abstract>
An overview over the C64 runtime system as it is implemented for the cc65 C
The names in the parentheses denote the symbols to be used for static linking of the drivers.
+<label id="graphics-drivers">
<sect1>Graphics drivers<p>
<em>Note:</em> All available graphics drivers for the TGI interface will use
-the space below the I/O area and kernal ROM, so you can have hires graphics in
-the standard setup without any memory loss or need for a changed
-configuration.
+the space below the I/O area and Kernal ROM; so, you can have hires graphics in
+the standard setup without any memory loss or need for a changed configuration.
+
+You can use a mouse driver at the same time that you use a TGI driver. But, if
+you want to see the default mouse pointer on the graphics screen, then you
+explicitly must link a special object file into your program. It will put the
+arrow into the "high RAM" area where the bitmaps are put. Its name is
+"<tt/c64-tgimousedata.o/". Example:
+
+<tscreen><verb>
+cl65 -t c64 -o program-file main-code.c subroutines.s c64-tgimousedata.o
+</verb></tscreen>
<descrip>
<tag><tt/c64-hi.tgi (c64_hi_tgi)/</tag>
Note that the graphics drivers are incompatible with the
<tt/c64-ram.emd (c64_ram_emd)/ extended memory driver and the
- <tt/c64-soft80.o/ software 80 columns conio driver.
+ <tt/c64-soft80.o/ software 80-columns conio driver.
+
<sect1>Extended memory drivers<p>
<descrip>
+ <tag><tt/c64-65816.emd (c64_65816_emd)/</tag>
+ Extended memory driver for 65816 (eg SCPU) based extra RAM.
+ Written and contributed by Marco van den Heuvel.
+
<tag><tt/c64-c256k.emd (c64_c256k_emd)/</tag>
A driver for the C64 256K memory expansion. This driver offers 768 pages of
256 bytes each. Written and contributed by Marco van den Heuvel.
<tag><tt/c64-ptvjoy.joy (c64_ptvjoy_joy)/</tag>
Driver for the Protovision 4-player adapter contributed by Groepaz. See
- <url url="http://www.protovision-online.de/hardw/hardwstart.htm"> for prices and
- building instructions. Up to four joysticks are supported.
+ <url url="http://www.protovision-online.de/hardw/4_player.php?language=en"
+ name="Protovision shop"> for prices and building instructions. Up to four
+ joysticks are supported.
<tag><tt/c64-stdjoy.joy (c64_stdjoy_joy)/</tag>
Supports up to two standard joysticks connected to the joysticks port of
<sect1>Mouse drivers<p>
+You can use these drivers in text-mode or graphics-mode (TGI) programs. See
+the description of <ref id="graphics-drivers" name="the graphics drivers">.
+
The default drivers, <tt/mouse_stddrv (mouse_static_stddrv)/, point to <tt/c64-1351.mou (c64_1351_mou)/.
<descrip>
<title>ca65 Users Guide
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
<url url="mailto:greg.king5@verizon.net" name="Greg King">
-<date>2015-11-17
+<date>2016-06-11
<abstract>
ca65 is a powerful macro assembler for the 6502, 65C02, and 65816 CPUs. It is
Set the default for the CPU type. The option takes a parameter, which
may be one of
- 6502, 65SC02, 65C02, 65816, sweet16, HuC6280
+ 6502, 6502X, 65SC02, 65C02, 65816, sweet16, HuC6280, 4510
<label id="option-create-dep">
<tt><ref id=".PSC02" name=".PSC02"></tt> command was given).
<item>all valid 65C02 mnemonics when in 65C02 mode (after the
<tt><ref id=".PC02" name=".PC02"></tt> command was given).
-<item>all valid 65618 mnemonics when in 65816 mode (after the
+<item>all valid 65816 mnemonics when in 65816 mode (after the
<tt><ref id=".P816" name=".P816"></tt> command was given).
+<item>all valid 4510 mnemonics when in 4510 mode (after the
+ <tt><ref id=".P4510" name=".P4510"></tt> command was given).
</itemize>
In 65816 mode, several aliases are accepted, in addition to the official
mnemonics:
-<tscreen><verb>
-CPA is an alias for CMP
-DEA is an alias for DEC A
-INA is an alias for INC A
-SWA is an alias for XBA
-TAD is an alias for TCD
-TAS is an alias for TCS
-TDA is an alias for TDC
-TSA is an alias for TSC
-</verb></tscreen>
+<itemize>
+<item><tt>CPA</tt> is an alias for <tt>CMP</tt>
+<item><tt>DEA</tt> is an alias for <tt>DEC A</tt>
+<item><tt>INA</tt> is an alias for <tt>INC A</tt>
+<item><tt>SWA</tt> is an alias for <tt>XBA</tt>
+<item><tt>TAD</tt> is an alias for <tt>TCD</tt>
+<item><tt>TAS</tt> is an alias for <tt>TCS</tt>
+<item><tt>TDA</tt> is an alias for <tt>TDC</tt>
+<item><tt>TSA</tt> is an alias for <tt>TSC</tt>
+</itemize>
<sect1>6502X mode<label id="6502X-mode"><p>
</itemize>
+<sect1>4510 mode<p>
+
+The 4510 is a microcontroller that is the core of the Commodore C65 aka C64DX.
+It contains among other functions a slightly modified 65CE02/4502 CPU, to allow
+address mapping for 20 bits of address space (1 megabyte addressable area).
+As compared to the description of the CPU in the
+<url url="http://www.zimmers.net/anonftp/pub/cbm/c65/c65manualupdated.txt.gz"
+name="C65 System Specification">
+<url url="https://raw.githubusercontent.com/MEGA65/c65-specifications/master/c65manualupdated.txt"
+name="(updated version)"> uses these changes:
+<itemize>
+<item><tt>LDA (d,SP),Y</tt> may also be written as <tt>LDA (d,S),Y</tt>
+(matching the 65816 notataion).
+<item>All branch instruction allow now 16 bit offsets. To use a 16 bit
+branch you have to prefix these with an "L" (e.g. "<tt>LBNE</tt>" instead of
+"<tt>BNE</tt>"). This might change at a later implementation of the assembler.
+</itemize>
+For more information about the Commodore C65/C64DX and the 4510 CPU, see
+<url url="http://www.zimmers.net/anonftp/pub/cbm/c65/"> and
+<url url="https://en.wikipedia.org/wiki/Commodore_65" name="Wikipedia">.
+
<sect1>sweet16 mode<label id="sweet16-mode"><p>
<sect1><tt>.CHARMAP</tt><label id=".CHARMAP"><p>
Apply a custom mapping for characters. The command is followed by two
- numbers. The first one is the index of the source character (range 1..255),
+ numbers. The first one is the index of the source character (range 0..255);
the second one is the mapping (range 0..255). The mapping applies to all
- character and string constants when they generate output, and overrides a
- mapping table specified with the <tt><ref id="option-t" name="-t"></tt>
+ character and string constants <em/when/ they generate output; and, overrides
+ a mapping table specified with the <tt><ref id="option-t" name="-t"></tt>
command line switch.
Example:
-
<tscreen><verb>
- .charmap $41, $61 ; Map 'A' to 'a'
+ .charmap $41, $61 ; Map 'A' to 'a'
</verb></tscreen>
at character is not allowed to start an identifier, even with this
feature enabled.
+ <tag><tt>bracket_as_indirect</tt><label id="bracket_as_indirect"></tag>
+
+ Use <tt>[]</tt> instead of <tt>()</tt> for the indirect addressing modes.
+ Example:
+
+ <tscreen><verb>
+ lda [$82]
+ lda [$82,x]
+ lda [$82],y
+ jmp [$fffe]
+ jmp [table,x]
+ </verb></tscreen>
+ <em/Note:/ This should not be used in 65186 mode because it conflicts with
+ the 65816 instruction syntax for far addressing. See the section covering
+ <tt/<ref id="address-sizes" name="address sizes">/ for more information.
+
<tag><tt>c_comments</tt><label id="c_comments"></tag>
Allow C like comments using <tt>/*</tt> and <tt>*/</tt> as left and right
Conditional assembly: Check if there are any remaining tokens in this line,
and evaluate to FALSE if this is the case, and to TRUE otherwise. If the
condition is not true, further lines are not assembled until an <tt><ref
- id=".ELSE" name=".ESLE"></tt>, <tt><ref id=".ELSEIF" name=".ELSEIF"></tt> or
+ id=".ELSE" name=".ELSE"></tt>, <tt><ref id=".ELSEIF" name=".ELSEIF"></tt> or
<tt><ref id=".ENDIF" name=".ENDIF"></tt> directive.
This command is often used to check if a macro parameter was given. Since an
(see <tt><ref id=".P02" name=".P02"></tt> command).
+<sect1><tt>.IFP4510</tt><label id=".IFP4510"><p>
+
+ Conditional assembly: Check if the assembler is currently in 4510 mode
+ (see <tt><ref id=".P4510" name=".P4510"></tt> command).
+
+
<sect1><tt>.IFP816</tt><label id=".IFP816"><p>
Conditional assembly: Check if the assembler is currently in 65816 mode
<tt><ref id="option--cpu" name="--cpu"></tt> command line option.
See: <tt><ref id=".PC02" name=".PC02"></tt>, <tt><ref id=".PSC02"
- name=".PSC02"></tt> and <tt><ref id=".P816" name=".P816"></tt>
+ name=".PSC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and
+ <tt><ref id=".P4510" name=".P4510"></tt>
+
+
+<sect1><tt>.P4510</tt><label id=".P4510"><p>
+
+ Enable the 4510 instruction set. This is a superset of the 65C02 and
+ 6502 instruction sets.
+
+ See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02"
+ name=".PSC02"></tt>, <tt><ref id=".PC02" name=".PC02"></tt> and
+ <tt><ref id=".P816" name=".P816"></tt>
<sect1><tt>.P816</tt><label id=".P816"><p>
6502 instruction sets.
See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02"
- name=".PSC02"></tt> and <tt><ref id=".PC02" name=".PC02"></tt>
+ name=".PSC02"></tt>, <tt><ref id=".PC02" name=".PC02"></tt> and
+ <tt><ref id=".P4510" name=".P4510"></tt>
<sect1><tt>.PAGELEN, .PAGELENGTH</tt><label id=".PAGELENGTH"><p>
6502 and 65SC02 instructions.
See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02"
- name=".PSC02"></tt> and <tt><ref id=".P816" name=".P816"></tt>
+ name=".PSC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and
+ <tt><ref id=".P4510" name=".P4510"></tt>
<sect1><tt>.POPCPU</tt><label id=".POPCPU"><p>
6502 instructions.
See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PC02"
- name=".PC02"></tt> and <tt><ref id=".P816" name=".P816"></tt>
+ name=".PC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and
+ <tt><ref id=".P4510" name=".P4510"></tt>
<sect1><tt>.PUSHCPU</tt><label id=".PUSHCPU"><p>
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 and HuC6280.
+ namely: 6502, 6502X, 65SC02, 65C02, 65816, 4510 and HuC6280.
See: <tt><ref id=".CPU" name=".CPU"></tt>,
<tt><ref id=".IFP02" name=".IFP02"></tt>,
<tt><ref id=".IFPSC02" name=".IFPSC02"></tt>,
<tt><ref id=".P02" name=".P02"></tt>,
<tt><ref id=".P816" name=".P816"></tt>,
+ <tt><ref id=".P4510" name=".P4510"></tt>,
<tt><ref id=".PC02" name=".PC02"></tt>,
<tt><ref id=".PSC02" name=".PSC02"></tt>
+<sect1><tt>.MACPACK apple2</tt><p>
+
+This macro package defines a macro named <tt/scrcode/. It takes a string
+as argument and places this string into memory translated into screen codes.
+
+
<sect1><tt>.MACPACK atari</tt><p>
This macro package defines a macro named <tt/scrcode/. It takes a string
CPU_65816
CPU_SWEET16
CPU_HUC6280
+ CPU_4510
</verb></tscreen>
is defined. These constants may be used to determine the exact type of the
CPU_ISET_65816
CPU_ISET_SWEET16
CPU_ISET_HUC6280
+ CPU_ISET_4510
</verb></tscreen>
The value read from the <tt/<ref id=".CPU" name=".CPU">/ pseudo variable may
<itemize>
<item><tt/__APPLE2__/ - Target system is <tt/apple2/ or <tt/apple2enh/
<item><tt/__APPLE2ENH__/ - Target system is <tt/apple2enh/
+<item><tt/__ATARI2600__/ - Target system is <tt/atari2600/
<item><tt/__ATARI5200__/ - Target system is <tt/atari5200/
<item><tt/__ATARI__/ - Target system is <tt/atari/ or <tt/atarixl/
<item><tt/__ATARIXL__/ - Target system is <tt/atarixl/
--- /dev/null
+<!doctype linuxdoc system>
+
+<article>
+<title>cc65 internals
+<author><url url="mailto:bbbradsmith@users.noreply.github.com" name="Brad Smith">
+<date>2016-02-27
+
+<abstract>
+Internal details of cc65 code generation,
+such as calling assembly functions from C.
+</abstract>
+
+<!-- Table of contents -->
+<toc>
+
+<!-- Begin the document -->
+
+
+
+<sect>Calling assembly functions from C<p>
+
+<sect1>Calling conventions<p>
+
+There are two calling conventions used in cc65:
+
+<itemize>
+ <item><tt/cdecl/ - passes all parameters on the C-stack.
+ <p>
+ <item><tt/fastcall/ - passes the rightmost parameter in
+ registers <tt>A/X/sreg</tt> and all others on the C-stack.
+ <p>
+</itemize>
+
+The default convention is <tt/fastcall/, but this can be changed with
+the <tt/--all-cdecl/ command line option. If a convention is specified in
+the function's declaration, that convention will be used instead.
+Variadic functions will always use <tt/cdecl/ convention.
+
+If the <tt/--standard/ command line option is used,
+the <tt/cdecl/ and <tt/fastcall/ keywords will not be available.
+The standard compliant variations <tt/__cdecl__/ and <tt/__fastcall__/ are always available.
+
+If a function has a prototype, parameters are pushed to the C-stack as their respective types
+(i.e. a <tt/char/ parameter will push 1 byte), but if a function has no prototype, default
+promotions will apply. This means that with no prototype, <tt/char/ will be promoted
+to <tt/int/ and be pushed as 2 bytes. K & R style function prototypes may be used,
+but they will function the same as if no prototype was used.
+
+<sect1>Prologue, before the function call<p>
+
+If the function is declared as fastcall, the rightmost argument will be loaded into
+the <tt>A/X/sreg</tt> registers:
+
+<itemize>
+ <item><tt/A/ - 8-bit parameter, or low byte of larger types<p>
+ <item><tt/X/ - 16-bit high byte, or second byte of 32-bits<p>
+ <item><tt/sreg/ - Zeropage pseudo-register including high 2 bytes of 32-bit parameter<p>
+</itemize>
+
+All other parameters will be pushed to the C-stack from left to right.
+The rightmost parameter will have the lowest address on the stack,
+and multi-byte parameters will have their least significant byte at the lower address.
+
+The <tt/sp/ pseudo-register is a zeropage pointer to the base of the C-stack.
+If the function has no prototype or is variadic
+the <tt/Y/ register will contain the number of bytes pushed to the stack for this function.
+
+Example:
+<tscreen><verb>
+// C prototype
+void cdecl foo(unsigned bar, unsigned char baz);
+
+; C-stack layout within the function:
+;
+; +------------------+
+; | High byte of bar |
+; Offset 2 ->+------------------+
+; | Low byte of bar |
+; Offset 1 ->+------------------+
+; | baz |
+; Offset 0 ->+------------------+
+
+; Example code for accessing bar. The variable is in A/X after this code snippet:
+;
+ ldy #2 ; Offset of high byte of bar
+ lda (sp),y ; High byte now in A
+ tax ; High byte now in X
+ dey ; Offset of low byte of bar
+ lda (sp),y ; Low byte now in A
+</verb></tscreen>
+
+<sect1>Epilogue, after the function call<p>
+
+<sect2>Return requirements<p>
+
+If the function has a return value, it will appear in the <tt>A/X/sreg</tt> registers.
+
+Functions with an 8-bit return value (<tt/char/ or <tt/unsigned char/) are expected
+to promote this value to a 16-bit integer on return, and store the high byte in <tt/X/.
+The compiler will depend on the promoted value in some cases (e.g. implicit conversion to <tt/int/),
+and failure to return the high byte in <tt/X/ will cause unexpected errors.
+This problem does not apply to the <tt/sreg/ pseudo-register, which is only
+used if the return type is 32-bit.
+
+If the function has a void return type, the compiler will not depend on the result
+of <tt>A/X/sreg</tt>, so these may be clobbered by the function.
+
+The C-stack pointer <tt/sp/ must be restored by the function to its value before the
+function call prologue. It may pop all of its parameters from the C-stack
+(e.g. using the <tt/runtime/ function <tt/popa/),
+or it could adjust <tt/sp/ directly.
+If the function has no prototype, or is variadic the <tt/Y/ register contains the
+number of bytes pushed to the stack on entry, which may be added to <tt/sp/ to restore its original state.
+
+The internal pseudo-register <tt/regbank/ must not be changed by the function.
+
+<sect2>Clobbered state<p>
+
+The <tt/Y/ register may be clobbered by the function.
+The compiler will not depend on its state after a function call.
+
+The <tt>A/X/sreg</tt> registers may be clobbered if any of them
+are not used by the return value (see above).
+
+Many of the internal pseudo-registers used by cc65 are available for
+free use by any function called by C, and do not need to be preserved.
+Note that if another C function is called from your assembly function,
+it may clobber any of these itself:
+
+<itemize>
+ <item><tt>tmp1 .. tmp4</tt><p>
+ <item><tt>ptr1 .. ptr4</tt><p>
+ <item><tt>regsave</tt><p>
+ <item><tt>sreg</tt> (if unused by return)<p>
+</itemize>
+
+
+
+</article>
+
<article>
<title>cc65 Users Guide
-<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
-<date>2015-05-26
+<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
+<url url="mailto:gregdk@users.sf.net" name="Greg King">
+<date>2016-06-11
<abstract>
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
<!-- Begin the document -->
-
<sect>Overview<p>
cc65 was originally a C compiler for the Atari 8-bit machines written by
<label id="option-W">
- <tag><tt>-W name[,name]</tt></tag>
+ <tag><tt>-W name[,name,...]</tt></tag>
This option allows to control warnings generated by the compiler. It is
- followed by a comma separated list of warnings that should be enabled or
+ followed by a comma-separated list of warnings that should be enabled or
disabled. To disable a warning, its name is prefixed by a minus sign. If
no such prefix exists, or the name is prefixed by a plus sign, the warning
is enabled.
- The following warning names are currently recognized:
+ The following warning names currently are recognized:
<descrip>
<tag><tt/const-comparison/</tag>
Warn if the result of a comparison is constant.
Treat all warnings as errors.
<tag><tt/no-effect/</tag>
Warn about statements that don't have an effect.
+ <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/struct-param/</tag>
Warn when passing structs by value.
<tag><tt/unknown-pragma/</tag>
- Warn about known #pragmas.
+ Warn about #pragmas that aren't recognized by cc65.
<tag><tt/unused-label/</tag>
Warn about unused labels.
<tag><tt/unused-param/</tag>
Warn about unused variables.
</descrip>
- The full list of available warning names may be retrieved by using the
+ The full list of available warning names can be retrieved by using the
option <tt><ref id="option-list-warnings" name="--list-warnings"></tt>.
- You may also use <tt><ref id="pragma-warn" name="#pragma warn"></tt> to
- control this setting for smaller pieces of code from within your code.
+ You may use also <tt><ref id="pragma-warn" name="#pragma warn"></tt> to
+ control this setting, for smaller pieces of code, from within your sources.
</descrip><p>
that you must not mix pointers to those functions with pointers to
user-written, cdecl functions (the calling conventions are incompatible).
<p>
-<item> The <tt/volatile/ keyword doesn't have an effect. This is not as bad
+<item> The <tt/volatile/ keyword has almost no effect. That is not as bad
as it sounds, since the 6502 has so few registers that it isn't
possible to keep values in registers anyway.
<p>
file. The syntax is
<tscreen><verb>
- asm (<string literal>[, optional parameters]) ;
+ asm [optional volatile] (<string literal>[, optional parameters]) ;
</verb></tscreen>
or
<tscreen><verb>
- __asm__ (<string literal>[, optional parameters]) ;
+ __asm__ [optional volatile] (<string literal>[, optional parameters]) ;
</verb></tscreen>
- The first form is in the user namespace and is disabled if the <tt/-A/
+ The first form is in the user namespace; and, is disabled if the <tt/-A/
switch is given.
There is a whole section covering inline assembler statements,
<p>
+
<sect>Predefined macros<p>
The compiler defines several macros at startup:
This macro is defined if the target is the enhanced Apple //e (-t apple2enh).
+ <tag><tt>__ATARI2600__</tt></tag>
+
+ This macro is defined if the target is the Atari 2600 game console.
+
<tag><tt>__ATARI5200__</tt></tag>
This macro is defined if the target is the Atari 5200 game console.
<sect1><tt>#pragma charmap (<index>, <code>)</tt><label id="pragma-charmap"><p>
Each literal string and each literal character in the source is translated
- by use of a translation table. This translation table is preset when the
- compiler is started depending on the target system, for example to map
- ISO-8859-1 characters into PETSCII if the target is a commodore machine.
+ by use of a translation table. That translation table is preset when the
+ compiler is started, depending on the target system; for example, to map
+ ISO-8859-1 characters into PETSCII if the target is a Commodore machine.
This pragma allows to change entries in the translation table, so the
translation for individual characters, or even the complete table may be
- adjusted.
+ adjusted. Both arguments are assumed to be unsigned characters with a valid
+ range of 0-255.
- Both arguments are assumed to be unsigned characters with a valid range of
- 1-255.
-
- Beware of two pitfalls:
-
- <itemize>
- <item>The character index is actually the code of the character in the
- C source, so character mappings do always depend on the source
- character set. This means that <tt/#pragma charmap/ is not
- portable -- it depends on the build environment.
- <item>While it is possible to use character literals as indices, the
- result may be somewhat unexpected, since character literals are
- itself translated. For this reason I would suggest to avoid
- character literals and use numeric character codes instead.
- </itemize>
+ Beware of some pitfalls:
+ <itemize>
+ <item>The character index is actually the code of the character in the
+ C source; so, character mappings do always depend on the source
+ character set. That means that <tt/#pragma charmap()/ is not
+ portable -- it depends on the build environment.
+ <item>While it is possible to use character literals as indices, the
+ result may be somewhat unexpected, since character literals are
+ themselves translated. For that reason, I would suggest to avoid
+ character literals, and use numeric character codes instead.
+ <item>It is risky to change index <tt/0x00/, because string functions depend
+ on it. If it is changed, then the <tt/'\0'/ at the end of string
+ literals will become non-zero. Functions that are used on those
+ literals won't stop at the end of them. cc65 will warn you if you do
+ change that code number. You can turn off that <tt/remap-zero/ warning
+ if you are certain that you know what you are doing (see <tt/<ref
+ id="pragma-warn" name="#pragma warn()">/).
+ </itemize>
Example:
<tscreen><verb>
- /* Use a space wherever an 'a' occurs in ISO-8859-1 source */
- #pragma charmap (0x61, 0x20);
+ /* Use a space wherever an 'a' occurs in ISO-8859-1 source */
+ #pragma charmap (0x61, 0x20);
</verb></tscreen>
Switch compiler warnings on or off. "name" is the name of a warning (see the
<tt/<ref name="-W" id="option-W">/ compiler option for a list). The name is
- either followed by "pop", which restores the last pushed state, or by "on" or
+ followed either by "pop", which restores the last pushed state, or by "on" or
"off", optionally preceeded by "push" to push the current state before
changing it.
#pragma warn (unused-param, pop)
</verb></tscreen>
+
<sect1><tt>#pragma writable-strings ([push,] on|off)</tt><label id="pragma-writable-strings"><p>
Changes the storage location of string literals. For historical reasons,
syntax is
<tscreen><verb>
- asm (<string literal>[, optional parameters]) ;
+ asm [optional volatile] (<string literal>[, optional parameters]) ;
</verb></tscreen>
or
<tscreen><verb>
- __asm__ (<string literal>[, optional parameters]) ;
+ __asm__ [optional volatile] (<string literal>[, optional parameters]) ;
</verb></tscreen>
<p>
-The first form is in the user namespace and is disabled by <tt><ref
+The first form is in the user namespace; and, is disabled by <tt><ref
id="option--standard" name="--standard"></tt> if the argument is not <tt/cc65/.
-The asm statement may be used inside a function and on global file level. An
-inline assembler statement is a primary expression, so it may also be used as
-part of an expression. Please note however that the result of an expression
-containing just an inline assembler statement is always of type <tt/void/.
+The <tt/asm/ statement can be used only inside a function. Please note that
+the result of an inline assembler expression is always of type <tt/void/.
-The contents of the string literal are preparsed by the compiler and inserted
-into the generated assembly output, so that the can be further processed by
-the backend and especially the optimizer. For this reason, the compiler does
-only allow regular 6502 opcodes to be used with the inline assembler. Pseudo
-instructions (like <tt/.import/, <tt/.byte/ and so on) are <em/not/ allowed,
+The contents of the string literal are preparsed by the compiler; and, inserted
+into the generated assembly output, so that it can be processed further by
+the backend -- and, especially the optimizer. For that reason, the compiler does
+allow only regular 6502 opcodes to be used with the inline assembler. Pseudo
+instructions (like <tt/.import/, <tt/.byte/, and so on) are <em/not/ allowed,
even if the ca65 assembler (which is used to translate the generated assembler
-code) would accept them. The builtin inline assembler is not a replacement for
-the full blown macro assembler which comes with the compiler.
+code) would accept them. The built-in inline assembler is not a replacement for
+the full-blown macro assembler which comes with the compiler.
Note: Inline assembler statements are subject to all optimizations done by the
-compiler. There is currently no way to protect an inline assembler statement
-from being moved or removed completely by the optimizer. If in doubt, check
-the generated assembler output, or disable optimizations.
+compiler. There currently is no way to protect an inline assembler statement
+-- alone -- from being moved or removed completely by the optimizer. If in
+doubt, check the generated assembler output; or, disable optimizations (for
+that function).
+
+As a shortcut, you can put the <tt/volatile/ qualifier in your <tt/asm/
+statements. It will disable optimization for the functions in which those
+<tt/asm volatile/ statements sit. The effect is the same as though you put
+</#pragma optimize(push, off)/ above those functions, and </#pragma
+optimize(pop)/ below those functions.
The string literal may contain format specifiers from the following list. For
each format specifier, an argument is expected which is inserted instead of
-the format specifier before passing the assembly code line to the backend.
+the format specifier, before passing the assembly code line to the backend.
<itemize>
<item><tt/%b/ - Numerical 8-bit value
<item><tt/%%/ - The % sign itself
</itemize><p>
-Using these format specifiers, you can access C <tt/#defines/, variables or
+Using those format specifiers, you can access C <tt/#defines/, variables, or
similar stuff from the inline assembler. For example, to load the value of
-a C <tt/#define/ into the Y register, one would use
+a C <tt/#define/ into the Y index register, one would use
<tscreen><verb>
- #define OFFS 23
- __asm__ ("ldy #%b", OFFS);
+ #define OFFS 23
+ __asm__ ("ldy #%b", OFFS);
</verb></tscreen>
Or, to access a struct member of a static variable:
<tscreen><verb>
- typedef struct {
- unsigned char x;
- unsigned char y;
- unsigned char color;
- } pixel_t;
- static pixel_t pixel;
- __asm__ ("ldy #%b", offsetof(pixel_t, color));
- __asm__ ("lda %v,y", pixel);
+ typedef struct {
+ unsigned char x;
+ unsigned char y;
+ unsigned char color;
+ } pixel_t;
+ static pixel_t pixel;
+ __asm__ ("ldy #%b", offsetof(pixel_t, color));
+ __asm__ ("lda %v,y", pixel);
</verb></tscreen>
<p>
The next example shows how to use global variables to exchange data between C
-an assembler and how to handle assembler jumps:
+and assembler; and, how to handle assembler jumps:
<tscreen><verb>
- unsigned char globalSubA, globalSubB, globalSubResult;
+ static unsigned char globalSubA, globalSubB, globalSubResult;
/* return a-b, return 255 if b>a */
unsigned char sub (unsigned char a, unsigned char b)
</verb></tscreen>
<p>
-Arrays can also be accessed:
+Arrays also can be accessed:
<tscreen><verb>
- unsigned char globalSquareTable[] = {
+ static const unsigned char globalSquareTable[] = {
0, 1, 4, 9, 16, 25, 36, 49, 64, 81,
100, 121, 144, 169, 196, 225
};
- unsigned char globalSquareA, globalSquareResult;
+ static unsigned char globalSquareA, globalSquareResult;
/* return a*a for a<16, else 255 */
unsigned char square (unsigned char a)
{
- if (a>15){
+ if (a > 15) {
return 255;
}
globalSquareA = a;
<p>
Note: Do not embed the assembler labels that are used as names of global
-variables or functions into your asm statements. Code like this
+variables or functions into your <tt/asm/ statements. Code such as this:
<tscreen><verb>
int foo;
- int bar () { return 1; }
- __asm__ ("lda _foo"); /* DON'T DO THAT! */
+ int bar (void) { return 1; }
+ ...
+ __asm__ ("lda _foo"); /* DON'T DO THAT! */
...
__asm__ ("jsr _bar"); /* DON'T DO THAT EITHER! */
</verb></tscreen>
<p>
-may stop working if the way, the compiler generates these names is changed in
-a future version. Instead use the format specifiers from the table above:
+might stop working if the way that the compiler generates those names is changed in
+a future version. Instead, use the format specifiers from the table above:
<tscreen><verb>
- __asm__ ("lda %v", foo); /* OK */
+ __asm__ ("lda %v", foo); /* OK */
...
__asm__ ("jsr %v", bar); /* OK */
</verb></tscreen>
<p>
+
<sect>Implementation-defined behavior<p>
This section describes the behavior of cc65 when the standard describes the
</enum>
</article>
-
+++ /dev/null
-<!doctype linuxdoc system> <!-- -*- text-mode -*- -->
-
-<article>
-<title>chrcvt Users Guide
-<author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">
-<date>2013-02-10
-
-<abstract>
-chrcvt is the vector font converter. It is able to convert a foreign font into
-the native format.
-</abstract>
-
-<!-- Table of contents -->
-<toc>
-
-<!-- Begin the document -->
-
-
-<sect>Overview<p>
-
-chrcvt is a vector font converter. It is able to convert a "BGI Stroked
-Font" to a compact TGI native vector font. See the function <url
-url="funcref.html#tgi_load_vectorfont" name="tgi_load_vectorfont"> for usage.
-
-
-
-<sect>Usage<p>
-
-The chrcvt utility converts the font of one Borland file to its cc65 equivalent.
-
-
-<sect1>Command line option overview<p>
-
-The program may be called as follows:
-
-<tscreen><verb>
----------------------------------------------------------------------------
-Usage: chrcvt [options] file [options] [file]
-Short options:
- -h Help (this text)
- -v Be more verbose
- -V Print the version number and exit
-
-Long options:
- --help Help (this text)
- --verbose Be more verbose
- --version Print the version number and exit
----------------------------------------------------------------------------
-</verb></tscreen>
-
-
-<sect1>Command line options in detail<p>
-
-Here is a description of all the command line options:
-
-<descrip>
-
- <tag><tt>-v, --verbose</tt></tag>
-
- Increase the converter verbosity.
-
-
- <tag><tt>-h, --help</tt></tag>
-
- Print the short option summary shown above.
-
-
- <tag><tt>-V, --version</tt></tag>
-
- Print the version number of the utility. When submitting a bug report,
- please include the operating system you're using, and the compiler
- version.
-</descrip>
-
-
-<sect>Input and output<p>
-
-The converter will read one CHR file per invocation and write the font
-in TCH format to a new file.
-
-Example output for the command
-<tscreen><verb>
-chrcvt --verbose LITT.CHR
-</verb></tscreen>
-<tscreen><verb>
-BGI Stroked Font V1.1 - Aug 12, 1991
-Copyright (c) 1987,1988 Borland International
-</verb></tscreen>
-
-
-
-<sect>Copyright<p>
-
-chrcvt is (C) Copyright 2009, Ullrich von Bassewitz. For usage of the
-binaries and/or sources the following conditions apply:
-
-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:
-
-<enum>
-<item> 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.
-<item> Altered source versions must be plainly marked as such, and must not
- be misrepresented as being the original software.
-<item> This notice may not be removed or altered from any source
- distribution.
-</enum>
-
-</article>
--- /dev/null
+<!doctype linuxdoc system> <!-- -*- text-mode -*- -->
+
+<article>
+<title>chrcvt65 Users Guide
+<author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">
+<date>2013-02-10
+
+<abstract>
+chrcvt65 is the vector font converter. It is able to convert a foreign font into
+the native format.
+</abstract>
+
+<!-- Table of contents -->
+<toc>
+
+<!-- Begin the document -->
+
+
+<sect>Overview<p>
+
+chrcvt65 is a vector font converter. It is able to convert a "BGI Stroked
+Font" to a compact TGI native vector font. See the function <url
+url="funcref.html#tgi_load_vectorfont" name="tgi_load_vectorfont"> for usage.
+
+
+
+<sect>Usage<p>
+
+The chrcvt65 utility converts the font of one Borland file to its cc65 equivalent.
+
+
+<sect1>Command line option overview<p>
+
+The program may be called as follows:
+
+<tscreen><verb>
+---------------------------------------------------------------------------
+Usage: chrcvt65 [options] file [options] [file]
+Short options:
+ -h Help (this text)
+ -v Be more verbose
+ -V Print the version number and exit
+
+Long options:
+ --help Help (this text)
+ --verbose Be more verbose
+ --version Print the version number and exit
+---------------------------------------------------------------------------
+</verb></tscreen>
+
+
+<sect1>Command line options in detail<p>
+
+Here is a description of all the command line options:
+
+<descrip>
+
+ <tag><tt>-v, --verbose</tt></tag>
+
+ Increase the converter verbosity.
+
+
+ <tag><tt>-h, --help</tt></tag>
+
+ Print the short option summary shown above.
+
+
+ <tag><tt>-V, --version</tt></tag>
+
+ Print the version number of the utility. When submitting a bug report,
+ please include the operating system you're using, and the compiler
+ version.
+</descrip>
+
+
+<sect>Input and output<p>
+
+The converter will read one CHR file per invocation and write the font
+in TCH format to a new file.
+
+Example output for the command
+<tscreen><verb>
+chrcvt65 --verbose LITT.CHR
+</verb></tscreen>
+<tscreen><verb>
+BGI Stroked Font V1.1 - Aug 12, 1991
+Copyright (c) 1987,1988 Borland International
+</verb></tscreen>
+
+
+
+<sect>Copyright<p>
+
+chrcvt65 is (C) Copyright 2009, Ullrich von Bassewitz. For usage of the
+binaries and/or sources the following conditions apply:
+
+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:
+
+<enum>
+<item> 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.
+<item> Altered source versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+<item> This notice may not be removed or altered from any source
+ distribution.
+</enum>
+
+</article>
-V Print the version number
-W name[,...] Supress compiler warnings
-Wa options Pass options to the assembler
+ -Wc options Pass options to the compiler
-Wl options Pass options to the linker
Long options:
--o65-model model Override the o65 model
--obj file Link this object file
--obj-path path Specify an object file search path
+ --print-target-path Print the target file path
--register-space b Set space available for register variables
--register-vars Enable register variables
--rodata-name seg Set the name of the RODATA segment
shouldn't use -o when more than one output file is created.
+ <tag><tt>--print-target-path</tt></tag>
+
+ This option prints the absolute path of the target file directory and exits
+ then. It is supposed to be used with shell backquotes or the GNU make shell
+ function. This way you can write build scripts or Makefiles accessing target
+ files without any assumption about the cc65 installation path.
+
+
<tag><tt>-t sys, --target sys</tt></tag>
The default for this option is different from the compiler and linker in the
the C64 as a target system by default. This was chosen since most people
seem to use cc65 to develop for the C64.
+
<tag><tt>-Wa options, --asm-args options</tt></tag>
Pass options directly to the assembler. This may be used to pass options
if cl65 supports an option by itself, do not pass this option to the
assembler by means of the <tt/-Wa/ switch.
+
<tag><tt>-Wc options, --cc-args options</tt></tag>
Pass options directly to the compiler. This may be used to pass options
if cl65 supports an option by itself, do not pass this option to the
compiler by means of the <tt/-Wc/ switch.
+
<tag><tt>-Wl options, --ld-args options</tt></tag>
Pass options directly to the linker. This may be used to pass options that
supports an option by itself, do not pass this option to the linker by means
of the <tt/-Wl/ switch.
-</descrip>
+</descrip>
</article>
-
<tscreen><code>
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp, define = yes;
- DATA: load = ROM, type = rw, define = yes, run = RAM;
- BSS: load = RAM, type = bss, define = yes;
- HEAP: load = RAM, type = bss, optional = yes;
- STARTUP: load = ROM, type = ro;
- INIT: load = ROM, type = ro, optional = yes;
- CODE: load = ROM, type = ro;
- RODATA: load = ROM, type = ro;
- VECTORS: load = ROM, type = ro, start = $FFFA;
+ ZEROPAGE: load = ZP, type = zp, define = yes;
+ DATA: load = ROM, type = rw, define = yes, run = RAM;
+ BSS: load = RAM, type = bss, define = yes;
+ HEAP: load = RAM, type = bss, optional = yes;
+ STARTUP: load = ROM, type = ro;
+ ONCE: load = ROM, type = ro, optional = yes;
+ CODE: load = ROM, type = ro;
+ RODATA: load = ROM, type = ro;
+ VECTORS: load = ROM, type = ro, start = $FFFA;
}
</code></tscreen>
<p><tt> BSS: </tt>Uninitialized data stored in RAM (used for variable storage)
<p><tt> HEAP: </tt>Uninitialized C-level heap storage in RAM, optional
<p><tt> STARTUP: </tt>The program initialization code, stored in ROM
-<p><tt> INIT: </tt>The code needed to initialize the system, stored in ROM
+<p><tt> ONCE: </tt>The code run once to initialize the system, stored in ROM
<p><tt> CODE: </tt>The program code, stored in ROM
<p><tt> RODATA: </tt>Initialized data that cannot be modified by the program, stored in ROM
<p><tt> VECTORS: </tt>The interrupt vector table, stored in ROM at location $FFFA
<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. Support for the 65816 currently is not available.
+ the PC engine. 4510 is the CPU of the Commodore C65. Support for the 65816
+ currently is not available.
<label id="option--formfeeds">
latter understands the same opcodes as the former, plus 16 additional bit
manipulation and bit test-and-branch commands.
+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
+branches point outside of the disassembled memory. This can happen when text
+or binary data is processed.
+
While there is some code for the 65816 in the sources, it is currently
unsupported.
<article>
<title>cc65 function reference
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
-<date>2015-07-21
+<date>2016-08-07
<abstract>
cc65 is a C compiler for 6502 based systems. This function reference describes
<!-- <item><ref id="_getcolor" name="_getcolor"> -->
<!-- <item><ref id="_getdefdev" name="_getdefdev"> -->
<!-- <item><ref id="_graphics" name="_graphics"> -->
+<item><ref id="_is_cmdline_dos" name="_is_cmdline_dos">
<!-- <item><ref id="_rest_vecs" name="_rest_vecs"> -->
<!-- <item><ref id="_save_vecs" name="_save_vecs"> -->
<!-- <item><ref id="_scroll" name="_scroll"> -->
<item><ref id="cbm_k_open" name="cbm_k_open">
<item><ref id="cbm_k_readst" name="cbm_k_readst">
<item><ref id="cbm_k_save" name="cbm_k_save">
+<item><ref id="cbm_k_scnkey" name="cbm_k_scnkey">
<item><ref id="cbm_k_setlfs" name="cbm_k_setlfs">
<item><ref id="cbm_k_setnam" name="cbm_k_setnam">
+<item><ref id="cbm_k_talk" name="cbm_k_talk">
+<item><ref id="cbm_k_udtim" name="cbm_k_udtim">
<item><ref id="cbm_k_unlsn" name="cbm_k_unlsn">
<!-- <item><ref id="cbm_load" name="cbm_load"> -->
<!-- <item><ref id="cbm_open" name="cbm_open"> -->
<sect1><tt/cc65.h/<label id="cc65.h"><p>
-<!-- <itemize> -->
+<itemize>
<!-- <item><ref id="cc65_cos" name="cc65_cos"> -->
<!-- <item><ref id="cc65_idiv32by16r16" name="cc65_idiv32by16r16"> -->
<!-- <item><ref id="cc65_imul16x16r32" name="cc65_imul16x16r32"> -->
<!-- <item><ref id="cc65_umul16x16r32" name="cc65_umul16x16r32"> -->
<!-- <item><ref id="cc65_umul16x8r32" name="cc65_umul16x8r32"> -->
<!-- <item><ref id="cc65_umul8x8r16" name="cc65_umul8x8r16"> -->
-<!-- </itemize> -->
+<item><ref id="doesclrscrafterexit" name="doesclrscrafterexit">
+</itemize>
(incomplete)
</itemize>
+<sect1><tt/gamate.h/<label id="gamate.h"><p>
+
+<!-- <itemize> -->
+<!-- <item><ref id="get_tv" name="get_tv"> -->
+<!-- <item><ref id="waitvblank" name="waitvblank"> -->
+<!-- </itemize> -->
+
+(incomplete)
+
+
<sect1><tt/geos.h/<label id="geos.h"><p>
(incomplete)
It does not declare any functions.
+<sect1><tt/pce.h/<label id="pce.h"><p>
+
+<!-- <itemize> -->
+<!-- <item><ref id="get_tv" name="get_tv"> -->
+<!-- <item><ref id="waitvblank" name="waitvblank"> -->
+<!-- </itemize> -->
+
+(incomplete)
+
+
<sect1><tt/peekpoke.h/<label id="peekpoke.h"><p>
<itemize>
</itemize>
+<sect1><tt/pen.h/<label id="pen.h"><p>
+
+<!-- <itemize> -->
+<!-- <item><ref id="pen_adjust" name="pen_adjust"> -->
+<!-- <item><ref id="pen_calibrate" name="pen_calibrate"> -->
+<!-- </itemize> -->
+
+(incomplete)
+
+
<sect1><tt/pet.h/<label id="pet.h"><p>
(incomplete)
</quote>
+<sect1>_is_cmdline_dos<label id="_is_cmdline_dos"><p>
+
+<quote>
+<descrip>
+<tag/Function/Determines whether the underlying DOS supports command line arguments.
+<tag/Header/<tt/<ref id="atari.h" name="atari.h">/
+<tag/Declaration/<tt/unsigned char _is_cmdline_dos (void);/
+<tag/Description/The function returns 0 if the DOS doesn't support command line arguments.
+It returns 1 if it does.
+<tag/Availability/cc65 (<tt/atari/ and <tt/atarixl/ platforms)
+</descrip>
+</quote>
+
+
<sect1>_poserror<label id="_poserror"><p>
<quote>
</quote>
+<sect1>cbm_k_scnkey<label id="cbm_k_scnkey"><p>
+
+<quote>
+<descrip>
+<tag/Function/Scan the keyboard matrix.
+<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/
+<tag/Declaration/<tt/void cbm_k_scnkey (void);/
+<tag/Description/This function looks at the switches in the keyboard, to see
+if any of them are being pressed. If they are, then code numbers for them are
+stored in RAM. Other functions use those numbers to input text. Normally,
+the keyboard is scanned by the Kernal's Interrupt Service Routine. But, if
+you divert the "Jiffy interrupt" to a C-code ISR, then that ISR must call this
+function, in order to provide input from the keyboard.
+<tag/Availability/cc65
+<tag/See also/
+<ref id="cbm_k_getin" name="cbm_k_getin">,
+<ref id="cbm_k_udtim" name="cbm_k_udtim">,
+<ref id="cgetc" name="cgetc">,
+<!-- <ref id="getc" name="getc"> -->
+<!-- <ref id="getchar" name="getchar"> -->
+<tag/Example/None.
+</descrip>
+</quote>
+
+
<sect1>cbm_k_setlfs<label id="cbm_k_setlfs"><p>
<quote>
</quote>
+<sect1>cbm_k_udtim<label id="cbm_k_udtim"><p>
+
+<quote>
+<descrip>
+<tag/Function/Update the Jiffy clock.
+<tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/
+<tag/Declaration/<tt/void cbm_k_udtim (void);/
+<tag/Description/This function adds one count to the Jiffy clock. That clock
+counts sixtieths of a second. It is used by the library's <tt/clock()/
+function. Normally, the Jiffy clock is updated by the Kernal's Interrupt
+Service Routine. But, if you divert the "Jiffy interrupt" to a C-code ISR,
+then that ISR must call this function, in order to keep the clock valid.
+<tag/Availability/cc65
+<tag/See also/
+<ref id="cbm_k_scnkey" name="cbm_k_scnkey">,
+<ref id="clock" name="clock">
+<tag/Example/None.
+</descrip>
+</quote>
+
+
<sect1>cbm_k_unlsn<label id="cbm_k_unlsn"><p>
<quote>
<tag/Header/<tt/<ref id="conio.h" name="conio.h">/
<tag/Declaration/<tt/char cgetc (void);/
<tag/Description/The function reads a character from the keyboard. If there is
-no character available, <tt/cgetc/ waits until the user presses a key. If the
+no character available, <tt/cgetc()/ waits until the user presses a key. If the
cursor is enabled by use of the <tt/cursor/ function, a blinking cursor is
displayed while waiting.
<tag/Notes/<itemize>
-<item>If the system supports a keyboard buffer, <tt/cgetc/ will fetch a key
-from this buffer and wait only if the buffer is empty.
+<item>If the system supports a keyboard buffer, <tt/cgetc()/ will fetch a key
+from that buffer; and, wait only if the buffer is empty.
+<item>The keyboard must be scanned periodically, in order for this function to
+see anything that you type. (See the description of <tt/cbm_k_scnkey()/.)
</itemize>
<tag/Availability/cc65
<tag/See also/
+<ref id="cbm_k_scnkey" name="cbm_k_scnkey">,
<ref id="cursor" name="cursor">,
<ref id="kbhit" name="kbhit">
<tag/Example/None.
<tag/Header/<tt/<ref id="time.h" name="time.h">/
<tag/Declaration/<tt/clock_t clock (void);/
<tag/Description/The <tt/clock/ function returns an approximaton of processor
-time used by the program. The time is returned in implementation defined
+time used by the program. The time is returned in implementation-defined
units. It can be converted to seconds by dividing by the value of the macro
<tt/CLOCKS_PER_SEC/.
<tag/Notes/<itemize>
-<item>Since the machines, cc65 generated programs run on, cannot run multiple
-processes, the function will actually return the time since some
-implementation defined point in the past.
+<item>Since the machines that cc65-generated programs run on cannot run multiple
+processes, the function actually will return the time since some
+implementation-defined point in the past.
+<item>The Jiffy clock must be "running", in order for this function to return
+changing values. (See the description of <tt/cbm_k_udtim()/.)
</itemize>
<tag/Availability/ISO 9899
<tag/See also/
+<ref id="cbm_k_udtim" name="cbm_k_udtim">,
<ref id="time" name="time">
<tag/Example/None.
</descrip>
</quote>
+<sect1>doesclrscrafterexit<label id="doesclrscrafterexit"><p>
+
+<quote>
+<descrip>
+<tag/Function/Determines whether the screen is going to be cleared after program exit.
+<tag/Header/<tt/<ref id="cc65.h" name="cc65.h">/
+<tag/Declaration/<tt/unsigned char doesclrscrafterexit (void);/
+<tag/Description/The function returns zero if the screen won't be cleared immediately after
+program termination. It returns a non-zero value if it will.
+<tag/Notes/<itemize>
+<item>Some systems, maybe depending on configuration, immediately clear the screen
+after a program exits. Therefore it might be difficult to read
+the last messages printed by the program prior to its exit. This function can be used
+to decide if a delay or wait for a key press should be executed when then program
+exits.
+</itemize>
+<tag/Availability/cc65
+<tag/Example/<verb>
+/* Hello World */
+#include <stdio.h>
+#include <unistd.h>
+#include <cc65.h>
+int main(void)
+{
+ printf("Hello World\n");
+ if (doesclrscrafterexit())
+ sleep(5);
+ return 0;
+}
+</verb>
+</descrip>
+</quote>
+
+
<sect1>em_commit<label id="em_commit"><p>
<quote>
<tag><htmlurl url="cc65.html" name="cc65.html"></tag>
Describes the cc65 C compiler.
- <tag><htmlurl url="chrcvt.html" name="chrcvt.html"></tag>
+ <tag><htmlurl url="chrcvt65.html" name="chrcvt65.html"></tag>
Describes the vector font converter.
<tag><htmlurl url="cl65.html" name="cl65.html"></tag>
Describes the da65 6502/65C02 disassembler.
<tag><htmlurl url="grc65.html" name="grc65.html"></tag>
- Describes the GEOS resource compiler (grc65).
+ Describes the GEOS resource compiler.
<tag><htmlurl url="ld65.html" name="ld65.html"></tag>
Describes the ld65 linker.
<tag><htmlurl url="coding.html" name="coding.html"></tag>
Contains hints on creating the most effective code with cc65.
+
+ <tag><htmlurl url="cc65-intern.html" name="cc65-intern.html"></tag>
+ Describes internal details of cc65, such as calling conventions.
<tag><htmlurl url="using-make.html" name="using-make.html"></tag>
Build programs, using the GNU Make utility.
<tag><htmlurl url="atari.html" name="atari.html"></tag>
Topics specific to the Atari 8-bit machines.
+ <tag><htmlurl url="atari2600.html" name="atari2600.html"></tag>
+ Topics specific to the Atari 2600 Game Console.
+
<tag><htmlurl url="atari5200.html" name="atari5200.html"></tag>
Topics specific to the Atari 5200 Game Console.
to the DOS menu. Your C program should wait for a keypress if you want to see
any output.
+<sect2>Stella<p>
+Available at <url
+url="http://stella.sourceforge.net">:
+
+Stella is a multi-platform Atari 2600 VCS emulator. The latest version
+is available on the emulator's website. It is also available through
+the package manager of most Linux distributions (Fedora, Ubuntu, ..).
+
+Compile the Atari 2600 sample with
+
+<tscreen><verb>
+make SYS=atari2600 samples
+</verb></tscreen>
+
+Then execute it with
+
+<tscreen><verb>
+stella samples/atari2600hello
+</verb></tscreen>
+
+<sect2>Harmony Cartridge<p>
+Available at <url
+url="http://harmony.atariage.com/Site/Harmony.html">:
+
+The Harmony Cartridge allows running any Atari 2600 binary on real
+hardware. The binary must be copied on an SD card, to be inserted in
+the Harmony Cartridge. It can then be inserted on an Atari 2600
+console, and run any binary on the SD card.
+
<sect1>Atmos
<item>module
<item>apple2
<item>apple2enh
+ <item>atari2600
<item>atari
<item>atarixl
<item>atmos
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>
+<sect1>ONCE<p>
-The INIT segment is used for initialization code that may be reused once
+The ONCE segment is used for initialization code run only once before
execution reaches main() - provided that the program runs in RAM. You
-may for example add the INIT segment to the heap in really memory
+may for example add the ONCE segment to the heap in really memory
constrained systems.
<sect1>LOWCODE<p>
<title>PC-Engine (TurboGrafx) System specific information for cc65
<author>
<url url="mailto:groepaz@gmx.net" name="Groepaz/Hitmen">
-<date>2015-07-14
+<date>2016-09-29
<abstract>
An overview over the PCE runtime system as it is implemented for the
<itemize>
<item><url url="http://blog.blockos.org/?tag=pc-engine">
<item><url url="http://pcedev.blockos.org/viewforum.php?f=5">
-<item><url url="http://www.romhacking.net/?page=documents&category=&platform=4&:game=&author=&perpage=20&level=&title=&desc=&docsearch=Go">
+<item><url url="http://www.romhacking.net/?page=documents&platform=4">
<item><url url="http://archaicpixels.com/Main_Page">
<item><url url="http://www.magicengine.com/mkit/doc.html">
<tag><tt/pet-ptvjoy.joy (pet_ptvjoy_joy)/</tag>
Driver for the Protovision 4-player adapter contributed by Groepaz. See
- <url url="http://www.protovision-online.de/hardw/hardwstart.htm"> for prices and
- building instructions. Up to two joysticks are supported.
+ <url url="http://www.protovision-online.de/hardw/4_player.php?language=en"
+ name="Protovision shop"> for prices and building instructions. Up to two
+ joysticks are supported.
<tag><tt/pet-stdjoy.joy (pet_stdjoy_joy)/</tag>
Driver for the standard PET userport joystick.
<title>sim65 Users Guide
<author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">
-<date>2016-01-05
+<date>2016-07-05
<abstract>
sim65 is a simulator for 6502 and 65C02 CPUs. It allows to test target
Usage: sim65 [options] file [arguments]
Short options:
-h Help (this text)
+ -c Print amount of executed CPU cycles
-v Increase verbosity
-V Print the simulator version number
-x <num> Exit simulator after <num> cycles
Long options:
--help Help (this text)
+ --cycles Print amount of executed CPU cycles
--verbose Increase verbosity
--version Print the simulator version number
</verb></tscreen>
Print the short option summary shown above.
+ <tag><tt>-c, --cycles</tt></tag>
+
+ Print the number of executed CPU cycles when the program terminates.
+ The cycles for the final "<tt>jmp exit</tt>" are not included in this
+ count.
+
+
<tag><tt>-v, --verbose</tt></tag>
Increase the simulator verbosity.
Long options:
--convert-to fmt[,attrlist] Convert into target format
+ --dump-palette Dump palette as table
--help Help (this text)
--list-conversions List all possible conversions
--pop Restore the original loaded image
see section <ref id="conversions" name="Conversions">.
+ <label id="option--dump-palette">
+ <tag><tt>--dump-palette</tt></tag>
+
+ Dump palette as table.
+
+
<label id="option--help">
<tag><tt>-h, --help</tt></tag>
<tag><tt/vic20-ptvjoy.joy (vic20_ptvjoy_joy)/</tag>
Driver for the Protovision 4-player adapter contributed by Groepaz. See
- <url url="http://www.protovision-online.de/hardw/hardwstart.htm"> for prices and
- building instructions. Up to three joysticks are supported.
+ <url url="http://www.protovision-online.de/hardw/4_player.php?language=en"
+ name="Protovision shop"> for prices and building instructions. Up to three
+ joysticks are supported.
</descrip><p>
#define CPU_6502 0
#define CPU_65C02 1
#define CPU_65816 2
+#define CPU_4510 3
unsigned char getcpu (void);
/* Detect the CPU the program is running on */
--- /dev/null
+/*****************************************************************************/
+/* */
+/* Atari VCS 2600 RIOT registers addresses */
+/* */
+/* Source: DASM - vcs.h */
+/* */
+/* Florent Flament (contact@florentflament.com), 2017 */
+/* */
+/*****************************************************************************/
+
+/* RIOT registers */
+struct __riot {
+ unsigned char swcha;
+ unsigned char swacnt;
+ unsigned char swchb;
+ unsigned char swbcnt;
+ unsigned char intim;
+ unsigned char timint;
+
+ unsigned char unused[14];
+
+ unsigned char tim1t;
+ unsigned char tim8t;
+ unsigned char tim64t;
+ unsigned char t1024t;
+};
--- /dev/null
+/*****************************************************************************/
+/* */
+/* Atari VCS 2600 TIA registers addresses */
+/* */
+/* Source: DASM - vcs.h */
+/* */
+/* Florent Flament (contact@florentflament.com), 2017 */
+/* */
+/*****************************************************************************/
+
+/* TIA write / read registers */
+struct __tia {
+ union {
+ unsigned char vsync;
+ unsigned char cxm0p;
+ };
+ union {
+ unsigned char vblank;
+ unsigned char cxm1p;
+ };
+ union {
+ unsigned char wsync;
+ unsigned char cxp0fb;
+ };
+ union {
+ unsigned char rsync;
+ unsigned char cxp1fb;
+ };
+ union {
+ unsigned char nusiz0;
+ unsigned char cxm0fb;
+ };
+ union {
+ unsigned char nusiz1;
+ unsigned char cxm1fb;
+ };
+ union {
+ unsigned char colup0;
+ unsigned char cxblpf;
+ };
+ union {
+ unsigned char colup1;
+ unsigned char cxppmm;
+ };
+ union {
+ unsigned char colupf;
+ unsigned char inpt0;
+ };
+ union {
+ unsigned char colubk;
+ unsigned char inpt1;
+ };
+ union {
+ unsigned char ctrlpf;
+ unsigned char inpt2;
+ };
+ union {
+ unsigned char refp0;
+ unsigned char inpt3;
+ };
+ union {
+ unsigned char refp1;
+ unsigned char inpt4;
+ };
+ union {
+ unsigned char pf0;
+ unsigned char inpt5;
+ };
+ unsigned char pf1;
+ unsigned char pf2;
+ unsigned char resp0;
+ unsigned char resp1;
+ unsigned char resm0;
+ unsigned char resm1;
+ unsigned char resbl;
+ unsigned char audc0;
+ unsigned char audc1;
+ unsigned char audf0;
+ unsigned char audf1;
+ unsigned char audv0;
+ unsigned char audv1;
+ unsigned char grp0;
+ unsigned char grp1;
+ unsigned char enam0;
+ unsigned char enam1;
+ unsigned char enabl;
+ unsigned char hmp0;
+ unsigned char hmp1;
+ unsigned char hmm0;
+ unsigned char hmm1;
+ unsigned char hmbl;
+ unsigned char vdelp0;
+ unsigned char vdelp1;
+ unsigned char vdelbl;
+ unsigned char resmp0;
+ unsigned char resmp1;
+ unsigned char hmove;
+ unsigned char hmclr;
+ unsigned char cxclr;
+};
/* numlines < 0 scrolls down */
/* misc. functions */
-extern unsigned char get_ostype(void); /* get ROM version */
-extern unsigned char get_tv(void); /* get TV system */
-extern void _save_vecs(void); /* save system vectors */
-extern void _rest_vecs(void); /* restore system vectors */
-extern char *_getdefdev(void); /* get default floppy device */
+extern unsigned char get_ostype(void); /* get ROM version */
+extern unsigned char get_tv(void); /* get TV system */
+extern void _save_vecs(void); /* save system vectors */
+extern void _rest_vecs(void); /* restore system vectors */
+extern char *_getdefdev(void); /* get default floppy device */
+extern unsigned char _is_cmdline_dos(void); /* does DOS support command lines */
/* global variables */
extern unsigned char _dos_type; /* the DOS flavour */
#define AT_PAL 1
/* valid _dos_type values */
-#define ATARIDOS 0
-#define SPARTADOS 1
-#define OSADOS 2
-#define MYDOS 3
-#define XDOS 4
+#define SPARTADOS 0
+#define OSADOS 1
+#define XDOS 2
+#define ATARIDOS 3
+#define MYDOS 4
#define NODOS 255
/* Define hardware */
--- /dev/null
+/*****************************************************************************/
+/* */
+/* Atari VCS 2600 TIA & RIOT registers addresses */
+/* */
+/* Source: DASM Version 1.05 - vcs.h */
+/* */
+/* Florent Flament (contact@florentflament.com), 2017 */
+/* */
+/*****************************************************************************/
+
+#ifndef _ATARI2600_H
+#define _ATARI2600_H
+
+/* Check for errors */
+#if !defined(__ATARI2600__)
+# error This module may only be used when compiling for the Atari 2600!
+#endif
+
+#include <_tia.h>
+#define TIA (*(struct __tia*)0x0000)
+
+#include <_riot.h>
+#define RIOT (*(struct __riot*)0x0280)
+
+/* End of atari2600.h */
+#endif /* #ifndef _ATARI2600_H */
--- /dev/null
+/*****************************************************************************/
+/* */
+/* atari_atascii_charmap.h */
+/* */
+/* Atari system standard string mapping (ISO-8859-1 -> AtASCII) */
+/* */
+/* */
+/* */
+/* (C) 2016 Christian Krueger */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+/* No include guard here! Multiple use in one file may be intentional. */
+
+#pragma charmap (0x00, 0x00)
+#pragma charmap (0x01, 0x01)
+#pragma charmap (0x02, 0x02)
+#pragma charmap (0x03, 0x03)
+#pragma charmap (0x04, 0x04)
+#pragma charmap (0x05, 0x05)
+#pragma charmap (0x06, 0x06)
+#pragma charmap (0x07, 0xFD)
+#pragma charmap (0x08, 0x08)
+#pragma charmap (0x09, 0x7F)
+#pragma charmap (0x0A, 0x9B)
+#pragma charmap (0x0B, 0x0B)
+#pragma charmap (0x0C, 0x7D)
+#pragma charmap (0x0D, 0x0D)
+#pragma charmap (0x0E, 0x0E)
+#pragma charmap (0x0F, 0x0F)
+
+#pragma charmap (0x10, 0x10)
+#pragma charmap (0x11, 0x11)
+#pragma charmap (0x12, 0x12)
+#pragma charmap (0x13, 0x13)
+#pragma charmap (0x14, 0x14)
+#pragma charmap (0x15, 0x15)
+#pragma charmap (0x16, 0x16)
+#pragma charmap (0x17, 0x17)
+#pragma charmap (0x18, 0x18)
+#pragma charmap (0x19, 0x19)
+#pragma charmap (0x1A, 0x1A)
+#pragma charmap (0x1B, 0x1B)
+#pragma charmap (0x1C, 0x1C)
+#pragma charmap (0x1D, 0x1D)
+#pragma charmap (0x1E, 0x1E)
+#pragma charmap (0x1F, 0x1F)
+
+#pragma charmap (0x20, 0x20)
+#pragma charmap (0x21, 0x21)
+#pragma charmap (0x22, 0x22)
+#pragma charmap (0x23, 0x23)
+#pragma charmap (0x24, 0x24)
+#pragma charmap (0x25, 0x25)
+#pragma charmap (0x26, 0x26)
+#pragma charmap (0x27, 0x27)
+#pragma charmap (0x28, 0x28)
+#pragma charmap (0x29, 0x29)
+#pragma charmap (0x2A, 0x2A)
+#pragma charmap (0x2B, 0x2B)
+#pragma charmap (0x2C, 0x2C)
+#pragma charmap (0x2D, 0x2D)
+#pragma charmap (0x2E, 0x2E)
+#pragma charmap (0x2F, 0x2F)
+
+#pragma charmap (0x30, 0x30)
+#pragma charmap (0x31, 0x31)
+#pragma charmap (0x32, 0x32)
+#pragma charmap (0x33, 0x33)
+#pragma charmap (0x34, 0x34)
+#pragma charmap (0x35, 0x35)
+#pragma charmap (0x36, 0x36)
+#pragma charmap (0x37, 0x37)
+#pragma charmap (0x38, 0x38)
+#pragma charmap (0x39, 0x39)
+#pragma charmap (0x3A, 0x3A)
+#pragma charmap (0x3B, 0x3B)
+#pragma charmap (0x3C, 0x3C)
+#pragma charmap (0x3D, 0x3D)
+#pragma charmap (0x3E, 0x3E)
+#pragma charmap (0x3F, 0x3F)
+
+#pragma charmap (0x40, 0x40)
+#pragma charmap (0x41, 0x41)
+#pragma charmap (0x42, 0x42)
+#pragma charmap (0x43, 0x43)
+#pragma charmap (0x44, 0x44)
+#pragma charmap (0x45, 0x45)
+#pragma charmap (0x46, 0x46)
+#pragma charmap (0x47, 0x47)
+#pragma charmap (0x48, 0x48)
+#pragma charmap (0x49, 0x49)
+#pragma charmap (0x4A, 0x4A)
+#pragma charmap (0x4B, 0x4B)
+#pragma charmap (0x4C, 0x4C)
+#pragma charmap (0x4D, 0x4D)
+#pragma charmap (0x4E, 0x4E)
+#pragma charmap (0x4F, 0x4F)
+
+#pragma charmap (0x50, 0x50)
+#pragma charmap (0x51, 0x51)
+#pragma charmap (0x52, 0x52)
+#pragma charmap (0x53, 0x53)
+#pragma charmap (0x54, 0x54)
+#pragma charmap (0x55, 0x55)
+#pragma charmap (0x56, 0x56)
+#pragma charmap (0x57, 0x57)
+#pragma charmap (0x58, 0x58)
+#pragma charmap (0x59, 0x59)
+#pragma charmap (0x5A, 0x5A)
+#pragma charmap (0x5B, 0x5B)
+#pragma charmap (0x5C, 0x5C)
+#pragma charmap (0x5D, 0x5D)
+#pragma charmap (0x5E, 0x5E)
+#pragma charmap (0x5F, 0x5F)
+
+#pragma charmap (0x60, 0x60)
+#pragma charmap (0x61, 0x61)
+#pragma charmap (0x62, 0x62)
+#pragma charmap (0x63, 0x63)
+#pragma charmap (0x64, 0x64)
+#pragma charmap (0x65, 0x65)
+#pragma charmap (0x66, 0x66)
+#pragma charmap (0x67, 0x67)
+#pragma charmap (0x68, 0x68)
+#pragma charmap (0x69, 0x69)
+#pragma charmap (0x6A, 0x6A)
+#pragma charmap (0x6B, 0x6B)
+#pragma charmap (0x6C, 0x6C)
+#pragma charmap (0x6D, 0x6D)
+#pragma charmap (0x6E, 0x6E)
+#pragma charmap (0x6F, 0x6F)
+
+#pragma charmap (0x70, 0x70)
+#pragma charmap (0x71, 0x71)
+#pragma charmap (0x72, 0x72)
+#pragma charmap (0x73, 0x73)
+#pragma charmap (0x74, 0x74)
+#pragma charmap (0x75, 0x75)
+#pragma charmap (0x76, 0x76)
+#pragma charmap (0x77, 0x77)
+#pragma charmap (0x78, 0x78)
+#pragma charmap (0x79, 0x79)
+#pragma charmap (0x7A, 0x7A)
+#pragma charmap (0x7B, 0x7B)
+#pragma charmap (0x7C, 0x7C)
+#pragma charmap (0x7D, 0x7D)
+#pragma charmap (0x7E, 0x7E)
+#pragma charmap (0x7F, 0x7F)
+
+#pragma charmap (0x80, 0x80)
+#pragma charmap (0x81, 0x81)
+#pragma charmap (0x82, 0x82)
+#pragma charmap (0x83, 0x83)
+#pragma charmap (0x84, 0x84)
+#pragma charmap (0x85, 0x85)
+#pragma charmap (0x86, 0x86)
+#pragma charmap (0x87, 0x87)
+#pragma charmap (0x88, 0x88)
+#pragma charmap (0x89, 0x89)
+#pragma charmap (0x8A, 0x8A)
+#pragma charmap (0x8B, 0x8B)
+#pragma charmap (0x8C, 0x8C)
+#pragma charmap (0x8D, 0x8D)
+#pragma charmap (0x8E, 0x8E)
+#pragma charmap (0x8F, 0x8F)
+
+#pragma charmap (0x90, 0x90)
+#pragma charmap (0x91, 0x91)
+#pragma charmap (0x92, 0x92)
+#pragma charmap (0x93, 0x93)
+#pragma charmap (0x94, 0x94)
+#pragma charmap (0x95, 0x95)
+#pragma charmap (0x96, 0x96)
+#pragma charmap (0x97, 0x97)
+#pragma charmap (0x98, 0x98)
+#pragma charmap (0x99, 0x99)
+#pragma charmap (0x9A, 0x9A)
+#pragma charmap (0x9B, 0x9B)
+#pragma charmap (0x9C, 0x9C)
+#pragma charmap (0x9D, 0x9D)
+#pragma charmap (0x9E, 0x9E)
+#pragma charmap (0x9F, 0x9F)
+
+#pragma charmap (0xA0, 0xA0)
+#pragma charmap (0xA1, 0xA1)
+#pragma charmap (0xA2, 0xA2)
+#pragma charmap (0xA3, 0xA3)
+#pragma charmap (0xA4, 0xA4)
+#pragma charmap (0xA5, 0xA5)
+#pragma charmap (0xA6, 0xA6)
+#pragma charmap (0xA7, 0xA7)
+#pragma charmap (0xA8, 0xA8)
+#pragma charmap (0xA9, 0xA9)
+#pragma charmap (0xAA, 0xAA)
+#pragma charmap (0xAB, 0xAB)
+#pragma charmap (0xAC, 0xAC)
+#pragma charmap (0xAD, 0xAD)
+#pragma charmap (0xAE, 0xAE)
+#pragma charmap (0xAF, 0xAF)
+
+#pragma charmap (0xB0, 0xB0)
+#pragma charmap (0xB1, 0xB1)
+#pragma charmap (0xB2, 0xB2)
+#pragma charmap (0xB3, 0xB3)
+#pragma charmap (0xB4, 0xB4)
+#pragma charmap (0xB5, 0xB5)
+#pragma charmap (0xB6, 0xB6)
+#pragma charmap (0xB7, 0xB7)
+#pragma charmap (0xB8, 0xB8)
+#pragma charmap (0xB9, 0xB9)
+#pragma charmap (0xBA, 0xBA)
+#pragma charmap (0xBB, 0xBB)
+#pragma charmap (0xBC, 0xBC)
+#pragma charmap (0xBD, 0xBD)
+#pragma charmap (0xBE, 0xBE)
+#pragma charmap (0xBF, 0xBF)
+
+#pragma charmap (0xC0, 0xC0)
+#pragma charmap (0xC1, 0xC1)
+#pragma charmap (0xC2, 0xC2)
+#pragma charmap (0xC3, 0xC3)
+#pragma charmap (0xC4, 0xC4)
+#pragma charmap (0xC5, 0xC5)
+#pragma charmap (0xC6, 0xC6)
+#pragma charmap (0xC7, 0xC7)
+#pragma charmap (0xC8, 0xC8)
+#pragma charmap (0xC9, 0xC9)
+#pragma charmap (0xCA, 0xCA)
+#pragma charmap (0xCB, 0xCB)
+#pragma charmap (0xCC, 0xCC)
+#pragma charmap (0xCD, 0xCD)
+#pragma charmap (0xCE, 0xCE)
+#pragma charmap (0xCF, 0xCF)
+
+#pragma charmap (0xD0, 0xD0)
+#pragma charmap (0xD1, 0xD1)
+#pragma charmap (0xD2, 0xD2)
+#pragma charmap (0xD3, 0xD3)
+#pragma charmap (0xD4, 0xD4)
+#pragma charmap (0xD5, 0xD5)
+#pragma charmap (0xD6, 0xD6)
+#pragma charmap (0xD7, 0xD7)
+#pragma charmap (0xD8, 0xD8)
+#pragma charmap (0xD9, 0xD9)
+#pragma charmap (0xDA, 0xDA)
+#pragma charmap (0xDB, 0xDB)
+#pragma charmap (0xDC, 0xDC)
+#pragma charmap (0xDD, 0xDD)
+#pragma charmap (0xDE, 0xDE)
+#pragma charmap (0xDF, 0xDF)
+
+#pragma charmap (0xE0, 0xE0)
+#pragma charmap (0xE1, 0xE1)
+#pragma charmap (0xE2, 0xE2)
+#pragma charmap (0xE3, 0xE3)
+#pragma charmap (0xE4, 0xE4)
+#pragma charmap (0xE5, 0xE5)
+#pragma charmap (0xE6, 0xE6)
+#pragma charmap (0xE7, 0xE7)
+#pragma charmap (0xE8, 0xE8)
+#pragma charmap (0xE9, 0xE9)
+#pragma charmap (0xEA, 0xEA)
+#pragma charmap (0xEB, 0xEB)
+#pragma charmap (0xEC, 0xEC)
+#pragma charmap (0xED, 0xED)
+#pragma charmap (0xEE, 0xEE)
+#pragma charmap (0xEF, 0xEF)
+
+#pragma charmap (0xF0, 0xF0)
+#pragma charmap (0xF1, 0xF1)
+#pragma charmap (0xF2, 0xF2)
+#pragma charmap (0xF3, 0xF3)
+#pragma charmap (0xF4, 0xF4)
+#pragma charmap (0xF5, 0xF5)
+#pragma charmap (0xF6, 0xF6)
+#pragma charmap (0xF7, 0xF7)
+#pragma charmap (0xF8, 0xF8)
+#pragma charmap (0xF9, 0xF9)
+#pragma charmap (0xFA, 0xFA)
+#pragma charmap (0xFB, 0xFB)
+#pragma charmap (0xFC, 0xFC)
+#pragma charmap (0xFD, 0xFD)
+#pragma charmap (0xFE, 0xFE)
+#pragma charmap (0xFF, 0xFF)
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* atari_screen_charmap.h */
+/* */
+/* Atari system internal string mapping (ISO-8859-1 -> Internal/Screen-Code) */
+/* */
+/* */
+/* */
+/* (C) 2016 Christian Krueger */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+/* No include guard here! Multiple use in one file may be intentional. */
+
+#pragma warn (remap-zero, push, off)
+#pragma charmap (0x00, 0x40)
+#pragma warn (remap-zero, pop)
+
+#pragma charmap (0x01, 0x41)
+#pragma charmap (0x02, 0x42)
+#pragma charmap (0x03, 0x43)
+#pragma charmap (0x04, 0x44)
+#pragma charmap (0x05, 0x45)
+#pragma charmap (0x06, 0x46)
+#pragma charmap (0x07, 0xFD)
+#pragma charmap (0x08, 0x48)
+#pragma charmap (0x09, 0x7F)
+#pragma charmap (0x0A, 0xDB)
+#pragma charmap (0x0B, 0x4B)
+#pragma charmap (0x0C, 0x7D)
+#pragma charmap (0x0D, 0x4D)
+#pragma charmap (0x0E, 0x4E)
+#pragma charmap (0x0F, 0x4F)
+
+#pragma charmap (0x10, 0x50)
+#pragma charmap (0x11, 0x51)
+#pragma charmap (0x12, 0x52)
+#pragma charmap (0x13, 0x53)
+#pragma charmap (0x14, 0x54)
+#pragma charmap (0x15, 0x55)
+#pragma charmap (0x16, 0x56)
+#pragma charmap (0x17, 0x57)
+#pragma charmap (0x18, 0x58)
+#pragma charmap (0x19, 0x59)
+#pragma charmap (0x1A, 0x5A)
+#pragma charmap (0x1B, 0x5B)
+#pragma charmap (0x1C, 0x5C)
+#pragma charmap (0x1D, 0x5D)
+#pragma charmap (0x1E, 0x5E)
+#pragma charmap (0x1F, 0x5F)
+
+#pragma warn (remap-zero, push, off)
+#pragma charmap (0x20, 0x00)
+#pragma warn (remap-zero, pop)
+
+#pragma charmap (0x21, 0x01)
+#pragma charmap (0x22, 0x02)
+#pragma charmap (0x23, 0x03)
+#pragma charmap (0x24, 0x04)
+#pragma charmap (0x25, 0x05)
+#pragma charmap (0x26, 0x06)
+#pragma charmap (0x27, 0x07)
+#pragma charmap (0x28, 0x08)
+#pragma charmap (0x29, 0x09)
+#pragma charmap (0x2A, 0x0A)
+#pragma charmap (0x2B, 0x0B)
+#pragma charmap (0x2C, 0x0C)
+#pragma charmap (0x2D, 0x0D)
+#pragma charmap (0x2E, 0x0E)
+#pragma charmap (0x2F, 0x0F)
+
+#pragma charmap (0x30, 0x10)
+#pragma charmap (0x31, 0x11)
+#pragma charmap (0x32, 0x12)
+#pragma charmap (0x33, 0x13)
+#pragma charmap (0x34, 0x14)
+#pragma charmap (0x35, 0x15)
+#pragma charmap (0x36, 0x16)
+#pragma charmap (0x37, 0x17)
+#pragma charmap (0x38, 0x18)
+#pragma charmap (0x39, 0x19)
+#pragma charmap (0x3A, 0x1A)
+#pragma charmap (0x3B, 0x1B)
+#pragma charmap (0x3C, 0x1C)
+#pragma charmap (0x3D, 0x1D)
+#pragma charmap (0x3E, 0x1E)
+#pragma charmap (0x3F, 0x1F)
+
+#pragma charmap (0x40, 0x20)
+#pragma charmap (0x41, 0x21)
+#pragma charmap (0x42, 0x22)
+#pragma charmap (0x43, 0x23)
+#pragma charmap (0x44, 0x24)
+#pragma charmap (0x45, 0x25)
+#pragma charmap (0x46, 0x26)
+#pragma charmap (0x47, 0x27)
+#pragma charmap (0x48, 0x28)
+#pragma charmap (0x49, 0x29)
+#pragma charmap (0x4A, 0x2A)
+#pragma charmap (0x4B, 0x2B)
+#pragma charmap (0x4C, 0x2C)
+#pragma charmap (0x4D, 0x2D)
+#pragma charmap (0x4E, 0x2E)
+#pragma charmap (0x4F, 0x2F)
+
+#pragma charmap (0x50, 0x30)
+#pragma charmap (0x51, 0x31)
+#pragma charmap (0x52, 0x32)
+#pragma charmap (0x53, 0x33)
+#pragma charmap (0x54, 0x34)
+#pragma charmap (0x55, 0x35)
+#pragma charmap (0x56, 0x36)
+#pragma charmap (0x57, 0x37)
+#pragma charmap (0x58, 0x38)
+#pragma charmap (0x59, 0x39)
+#pragma charmap (0x5A, 0x3A)
+#pragma charmap (0x5B, 0x3B)
+#pragma charmap (0x5C, 0x3C)
+#pragma charmap (0x5D, 0x3D)
+#pragma charmap (0x5E, 0x3E)
+#pragma charmap (0x5F, 0x3F)
+
+#pragma charmap (0x60, 0x60)
+#pragma charmap (0x61, 0x61)
+#pragma charmap (0x62, 0x62)
+#pragma charmap (0x63, 0x63)
+#pragma charmap (0x64, 0x64)
+#pragma charmap (0x65, 0x65)
+#pragma charmap (0x66, 0x66)
+#pragma charmap (0x67, 0x67)
+#pragma charmap (0x68, 0x68)
+#pragma charmap (0x69, 0x69)
+#pragma charmap (0x6A, 0x6A)
+#pragma charmap (0x6B, 0x6B)
+#pragma charmap (0x6C, 0x6C)
+#pragma charmap (0x6D, 0x6D)
+#pragma charmap (0x6E, 0x6E)
+#pragma charmap (0x6F, 0x6F)
+
+#pragma charmap (0x70, 0x70)
+#pragma charmap (0x71, 0x71)
+#pragma charmap (0x72, 0x72)
+#pragma charmap (0x73, 0x73)
+#pragma charmap (0x74, 0x74)
+#pragma charmap (0x75, 0x75)
+#pragma charmap (0x76, 0x76)
+#pragma charmap (0x77, 0x77)
+#pragma charmap (0x78, 0x78)
+#pragma charmap (0x79, 0x79)
+#pragma charmap (0x7A, 0x7A)
+#pragma charmap (0x7B, 0x7B)
+#pragma charmap (0x7C, 0x7C)
+#pragma charmap (0x7D, 0x7D)
+#pragma charmap (0x7E, 0x7E)
+#pragma charmap (0x7F, 0x7F)
+
+#pragma charmap (0x80, 0xC0)
+#pragma charmap (0x81, 0xC1)
+#pragma charmap (0x82, 0xC2)
+#pragma charmap (0x83, 0xC3)
+#pragma charmap (0x84, 0xC4)
+#pragma charmap (0x85, 0xC5)
+#pragma charmap (0x86, 0xC6)
+#pragma charmap (0x87, 0xC7)
+#pragma charmap (0x88, 0xC8)
+#pragma charmap (0x89, 0xC9)
+#pragma charmap (0x8A, 0xCA)
+#pragma charmap (0x8B, 0xCB)
+#pragma charmap (0x8C, 0xCC)
+#pragma charmap (0x8D, 0xCD)
+#pragma charmap (0x8E, 0xCE)
+#pragma charmap (0x8F, 0xCF)
+
+#pragma charmap (0x90, 0xD0)
+#pragma charmap (0x91, 0xD1)
+#pragma charmap (0x92, 0xD2)
+#pragma charmap (0x93, 0xD3)
+#pragma charmap (0x94, 0xD4)
+#pragma charmap (0x95, 0xD5)
+#pragma charmap (0x96, 0xD6)
+#pragma charmap (0x97, 0xD7)
+#pragma charmap (0x98, 0xD8)
+#pragma charmap (0x99, 0xD9)
+#pragma charmap (0x9A, 0xDA)
+#pragma charmap (0x9B, 0xDB)
+#pragma charmap (0x9C, 0xDC)
+#pragma charmap (0x9D, 0xDD)
+#pragma charmap (0x9E, 0xDE)
+#pragma charmap (0x9F, 0xDF)
+
+#pragma charmap (0xA0, 0x80)
+#pragma charmap (0xA1, 0x81)
+#pragma charmap (0xA2, 0x82)
+#pragma charmap (0xA3, 0x83)
+#pragma charmap (0xA4, 0x84)
+#pragma charmap (0xA5, 0x85)
+#pragma charmap (0xA6, 0x86)
+#pragma charmap (0xA7, 0x87)
+#pragma charmap (0xA8, 0x88)
+#pragma charmap (0xA9, 0x89)
+#pragma charmap (0xAA, 0x8A)
+#pragma charmap (0xAB, 0x8B)
+#pragma charmap (0xAC, 0x8C)
+#pragma charmap (0xAD, 0x8D)
+#pragma charmap (0xAE, 0x8E)
+#pragma charmap (0xAF, 0x8F)
+
+#pragma charmap (0xB0, 0x90)
+#pragma charmap (0xB1, 0x91)
+#pragma charmap (0xB2, 0x92)
+#pragma charmap (0xB3, 0x93)
+#pragma charmap (0xB4, 0x94)
+#pragma charmap (0xB5, 0x95)
+#pragma charmap (0xB6, 0x96)
+#pragma charmap (0xB7, 0x97)
+#pragma charmap (0xB8, 0x98)
+#pragma charmap (0xB9, 0x99)
+#pragma charmap (0xBA, 0x9A)
+#pragma charmap (0xBB, 0x9B)
+#pragma charmap (0xBC, 0x9C)
+#pragma charmap (0xBD, 0x9D)
+#pragma charmap (0xBE, 0x9E)
+#pragma charmap (0xBF, 0x9F)
+
+#pragma charmap (0xC0, 0xA0)
+#pragma charmap (0xC1, 0xA1)
+#pragma charmap (0xC2, 0xA2)
+#pragma charmap (0xC3, 0xA3)
+#pragma charmap (0xC4, 0xA4)
+#pragma charmap (0xC5, 0xA5)
+#pragma charmap (0xC6, 0xA6)
+#pragma charmap (0xC7, 0xA7)
+#pragma charmap (0xC8, 0xA8)
+#pragma charmap (0xC9, 0xA9)
+#pragma charmap (0xCA, 0xAA)
+#pragma charmap (0xCB, 0xAB)
+#pragma charmap (0xCC, 0xAC)
+#pragma charmap (0xCD, 0xAD)
+#pragma charmap (0xCE, 0xAE)
+#pragma charmap (0xCF, 0xAF)
+
+#pragma charmap (0xD0, 0xB0)
+#pragma charmap (0xD1, 0xB1)
+#pragma charmap (0xD2, 0xB2)
+#pragma charmap (0xD3, 0xB3)
+#pragma charmap (0xD4, 0xB4)
+#pragma charmap (0xD5, 0xB5)
+#pragma charmap (0xD6, 0xB6)
+#pragma charmap (0xD7, 0xB7)
+#pragma charmap (0xD8, 0xB8)
+#pragma charmap (0xD9, 0xB9)
+#pragma charmap (0xDA, 0xBA)
+#pragma charmap (0xDB, 0xBB)
+#pragma charmap (0xDC, 0xBC)
+#pragma charmap (0xDD, 0xBD)
+#pragma charmap (0xDE, 0xBE)
+#pragma charmap (0xDF, 0xBF)
+
+#pragma charmap (0xE0, 0xE0)
+#pragma charmap (0xE1, 0xE1)
+#pragma charmap (0xE2, 0xE2)
+#pragma charmap (0xE3, 0xE3)
+#pragma charmap (0xE4, 0xE4)
+#pragma charmap (0xE5, 0xE5)
+#pragma charmap (0xE6, 0xE6)
+#pragma charmap (0xE7, 0xE7)
+#pragma charmap (0xE8, 0xE8)
+#pragma charmap (0xE9, 0xE9)
+#pragma charmap (0xEA, 0xEA)
+#pragma charmap (0xEB, 0xEB)
+#pragma charmap (0xEC, 0xEC)
+#pragma charmap (0xED, 0xED)
+#pragma charmap (0xEE, 0xEE)
+#pragma charmap (0xEF, 0xEF)
+
+#pragma charmap (0xF0, 0xF0)
+#pragma charmap (0xF1, 0xF1)
+#pragma charmap (0xF2, 0xF2)
+#pragma charmap (0xF3, 0xF3)
+#pragma charmap (0xF4, 0xF4)
+#pragma charmap (0xF5, 0xF5)
+#pragma charmap (0xF6, 0xF6)
+#pragma charmap (0xF7, 0xF7)
+#pragma charmap (0xF8, 0xF8)
+#pragma charmap (0xF9, 0xF9)
+#pragma charmap (0xFA, 0xFA)
+#pragma charmap (0xFB, 0xFB)
+#pragma charmap (0xFC, 0xFC)
+#pragma charmap (0xFD, 0xFD)
+#pragma charmap (0xFE, 0xFE)
+#pragma charmap (0xFF, 0xFF)
+
unsigned char cbm_k_open (void);
unsigned char cbm_k_readst (void);
unsigned char __fastcall__ cbm_k_save(unsigned int start, unsigned int end);
+void cbm_k_scnkey (void);
void __fastcall__ cbm_k_setlfs (unsigned char LFN, unsigned char DEV,
unsigned char SA);
void __fastcall__ cbm_k_setnam (const char* Name);
void __fastcall__ cbm_k_talk (unsigned char dev);
+void cbm_k_udtim (void);
void cbm_k_unlsn (void);
** is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00.
*/
+unsigned char doesclrscrafterexit (void);
+/* Indicates whether the screen automatically be cleared after program
+** termination.
+*/
+
/* End of cc65.h */
#define ESPIPE 14 /* Illegal seek */
#define ERANGE 15 /* Range error */
#define EBADF 16 /* Bad file number */
-#define EUNKNOWN 17 /* Unknown OS specific error */
+#define ENOEXEC 17 /* Exec format error */
+#define EUNKNOWN 18 /* Unknown OS specific error */
+
ifneq ($(shell echo),)
CMD_EXE = 1
endif
apple2enh \
atari \
atarixl \
+ atari2600 \
atari5200 \
atmos \
creativision \
ser \
tgi
-OUTPUTDIRS := lib \
- $(DRVTYPES) \
- targetutil \
- asminc \
- cfg \
- include \
- $(subst ../,,$(filter-out $(wildcard ../include/*.*),$(wildcard ../include/*)))
+OUTPUTDIRS := lib \
+ asminc \
+ cfg \
+ include \
+ $(subst ../,,$(filter-out $(wildcard ../include/*.*),$(wildcard ../include/*)))\
+ $(subst ../,,$(wildcard ../target/*/drv/*))\
+ $(subst ../,,$(wildcard ../target/*/util))\
.PHONY: all mostlyclean clean install zip lib $(TARGETS)
$(call RMDIR,../libwrk)
clean:
- $(call RMDIR,../libwrk ../lib ../targetutil $(addprefix ../,$(DRVTYPES)))
+ $(call RMDIR,../libwrk ../lib ../target)
ifdef CMD_EXE
$(if $(prefix),,$(error variable `prefix' must be set))
$(INSTALL) -d $(DESTDIR)$(datadir)/$(dir)
-$(INSTALL) -m644 ../$(dir)/*.* $(DESTDIR)$(datadir)/$(dir)
+$(INSTALL) -m0644 ../$(dir)/*.* $(DESTDIR)$(datadir)/$(dir)
endef # INSTALL_recipe
$1_SRCDIR = $$(SRCDIR)/$1
$1_STCDIR = ../libwrk/$$(TARGET)
$1_DYNDIR = ../libwrk/$$(TARGET)/$1
-$1_DRVDIR = ../$1
+$1_DRVDIR = ../target/$$(TARGET)/drv/$1
$1_SRCPAT = $$($1_SRCDIR)/$$(OBJPFX)%.s
$1_STCPAT = $$($1_STCDIR)/$$(OBJPFX)%-$1.o
../lib/$(TARGET).lib: $(OBJS) | ../lib
$(AR65) a $@ $?
-../libwrk/$(TARGET) ../lib ../targetutil:
+../libwrk/$(TARGET) ../lib ../target/$(TARGET)/util:
@$(call MKDIR,$@)
$(TARGET): $(EXTRA_OBJS) ../lib/$(TARGET).lib
--- /dev/null
+;
+; void __fastcall__ _sys (struct regs* r);
+;
+
+ .export __sys
+ .import jmpvec
+
+ .include "zeropage.inc"
+
+ .segment "LOWCODE"
+
+__sys: sta ptr1
+ stx ptr1+1 ; Save the pointer to r
+
+ ; Fetch the PC and store it into the jump vector
+ ldy #5
+ lda (ptr1),y
+ sta jmpvec+2
+ dey
+ lda (ptr1),y
+ sta jmpvec+1
+
+ ; Remember the flags so we can restore them to a known state after calling the
+ ; routine
+ php
+
+ ; Get the flags, keep the state of bit 4 and 5 using the other flags from
+ ; the flags value passed by the caller. Push the new flags and push A.
+ dey
+ php
+ pla ; Current flags -> A
+ eor (ptr1),y
+ and #%00110000
+ eor (ptr1),y
+ pha ; Push new flags value
+ ldy #0
+ lda (ptr1),y
+ pha
+
+ ; Get and assign X and Y
+ iny
+ lda (ptr1),y
+ tax
+ iny
+ lda (ptr1),y
+ tay
+
+ ; Switch in ROM
+ bit $C082
+
+ ; Set A and the flags, call the machine code routine
+ pla
+ plp
+ jsr jmpvec
+
+ ; Back from the routine. Save the flags and A.
+ php
+ pha
+
+ ; Switch in LC bank 2 for R/O
+ bit $C080
+
+ ; Put the register values into the regs structure
+ tya
+ ldy #2
+ sta (ptr1),y
+ dey
+ txa
+ sta (ptr1),y
+ dey
+ pla
+ sta (ptr1),y
+ ldy #3
+ pla
+ sta (ptr1),y
+
+ ; Restore the old flags value
+ plp
+
+ ; Done
+ rts
;
.export _cclearxy, _cclear
- .import popa, _gotoxy, chlinedirect
+ .import gotoxy, chlinedirect
_cclearxy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cclear
_cclear:
; If open_apple key is pressed then the high-bit of the key is set.
;
- .export _cgetc
+ .export _cgetc
+ .import cursor, putchardirect
- .include "apple2.inc"
+ .include "apple2.inc"
_cgetc:
- lda KBD
- bpl _cgetc ; If < 128, no key pressed
+ ; Cursor on ?
+ lda cursor
+ beq :+
- ; At this time, the high bit of the key pressed is set
- bit KBDSTRB ; Clear keyboard strobe
+ ; Show caret.
+ .ifdef __APPLE2ENH__
+ lda #$7F | $80 ; Checkerboard, screen code
+ .else
+ lda #' ' | $40 ; Blank, flashing
+ .endif
+ jsr putchardirect ; Returns old character in X
+
+ ; Wait for keyboard strobe.
+: lda KBD
+ bpl :- ; If < 128, no key pressed
+
+ ; Cursor on ?
+ ldy cursor
+ beq :+
+
+ ; Restore old character.
+ pha
+ txa
+ jsr putchardirect
+ pla
+
+ ; At this time, the high bit of the key pressed is set.
+: bit KBDSTRB ; Clear keyboard strobe
.ifdef __APPLE2ENH__
bit BUTN0 ; Check if OpenApple is down
bmi done
.endif
and #$7F ; If not down, then clear high bit
-done: ldx #$00
+done: ldx #>$0000
rts
;
.export _chlinexy, _chline, chlinedirect
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.include "zeropage.inc"
.include "apple2.inc"
_chlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _chline
_chline:
ldx #'-' | $80 ; Horizontal line, screen code
chlinedirect:
+ stx tmp1
cmp #$00 ; Is the length zero?
beq done ; Jump if done
- sta tmp1
-: txa ; Screen code
+ sta tmp2
+: lda tmp1 ; Screen code
jsr cputdirect ; Direct output
- dec tmp1
+ dec tmp2
bne :-
done: rts
.constructor initconio
.endif
.export _cputcxy, _cputc
- .export cputdirect, newline, putchar
- .import popa, _gotoxy, VTABZ
+ .export cputdirect, newline, putchar, putchardirect
+ .import gotoxy, VTABZ
.include "apple2.inc"
- .segment "INIT"
+ .segment "ONCE"
.ifdef __APPLE2ENH__
initconio:
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy
- pla ; Restore C
+ jsr gotoxy ; Call this one, will pop params
+ pla ; Restore C and run into _cputc
_cputc:
cmp #$0D ; Test for \r = carrage return
lda WNDTOP ; Goto top of screen
sta CV
: jmp VTABZ
-
+
putchar:
.ifdef __APPLE2ENH__
ldy INVFLG
cpy #$FF ; Normal character display mode?
- beq put
+ beq putchardirect
cmp #$E0 ; Lowercase?
bcc mask
and #$7F ; Inverse lowercase
- bra put
+ bra putchardirect
.endif
mask: and INVFLG ; Apply normal, inverse, flash
-put: ldy CH
+
+putchardirect:
+ pha
+ ldy CH
.ifdef __APPLE2ENH__
bit RD80VID ; In 80 column mode?
- bpl col40 ; No, in 40 cols
- pha
+ bpl put ; No, just go ahead
tya
lsr ; Div by 2
tay
- pla
- bcs col40 ; Odd cols go in 40 col memory
+ bcs put ; Odd cols go in main memory
bit HISCR ; Assume SET80COL
+ .endif
+put: lda (BASL),Y ; Get current character
+ tax ; Return old character for _cgetc
+ pla
sta (BASL),Y
- bit LOWSCR ; Assume SET80COL
- rts
+ .ifdef __APPLE2ENH__
+ bit LOWSCR ; Doesn't hurt in 40 column mode
.endif
-col40: sta (BASL),Y
rts
.export _exit, done, return
.export __STARTUP__ : absolute = 1 ; Mark as startup
- .import zerobss
+
.import initlib, donelib
- .import callmain
+ .import zerobss, callmain
+ .import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated
.import __LC_START__, __LC_LAST__ ; Linker generated
- .import __INIT_RUN__, __INIT_SIZE__ ; Linker generated
- .import __INITBSS_RUN__ ; Linker generated
.include "zeropage.inc"
.include "apple2.inc"
+; ------------------------------------------------------------------------
+
.segment "STARTUP"
; ProDOS TechRefMan, chapter 5.2.1:
ldx #$FF
txs ; Init stack pointer
- ; Switch in LC bank 2 for W/O.
- bit $C081
- bit $C081
-
- ; Set the source start address.
- lda #<(__INITBSS_RUN__ + __INIT_SIZE__)
- ldy #>(__INITBSS_RUN__ + __INIT_SIZE__)
- sta $9B
- sty $9C
-
- ; Set the source last address.
- lda #<(__INITBSS_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__)
- ldy #>(__INITBSS_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__)
- sta $96
- sty $97
-
- ; Set the destination last address.
- lda #<__LC_LAST__
- ldy #>__LC_LAST__
- sta $94
- sty $95
-
- ; Call into Applesoft Block Transfer Up -- which handles zero-
- ; sized blocks well -- to move the content of the LC memory area.
- jsr $D39A ; BLTU2
-
- ; Set the source start address.
- lda #<__INITBSS_RUN__
- ldy #>__INITBSS_RUN__
- sta $9B
- sty $9C
-
- ; Set the source last address.
- lda #<(__INITBSS_RUN__ + __INIT_SIZE__)
- ldy #>(__INITBSS_RUN__ + __INIT_SIZE__)
- sta $96
- sty $97
-
- ; Set the destination last address.
- lda #<(__INIT_RUN__ + __INIT_SIZE__)
- ldy #>(__INIT_RUN__ + __INIT_SIZE__)
- sta $94
- sty $95
+ ; Save space by putting some of the start-up code in the ONCE segment,
+ ; which can be re-used by the BSS segment, the heap and the C stack.
+ jsr init
- ; Call into Applesoft Block Transfer Up -- which handles moving
- ; overlapping blocks upwards well -- to move the INIT segment.
- jsr $D39A ; BLTU2
+ ; Clear the BSS data.
+ jsr zerobss
- ; Delegate all further processing, to keep the STARTUP segment small.
- jsr init
+ ; Push the command-line arguments; and, call main().
+ jsr callmain
; Avoid a re-entrance of donelib. This is also the exit() entry.
_exit: ldx #<exit
; We're done
jmp done
- .segment "INIT"
+; ------------------------------------------------------------------------
+
+ .segment "ONCE"
; Save the zero-page locations that we need.
init: ldx #zpspace-1
dex
bpl :-
- ; Clear the BSS data.
- jsr zerobss
-
; Save the original RESET vector.
ldx #$02
: lda SOFTEV,x
dex
bpl :-
- ; ProDOS TechRefMan, chapter 5.3.5:
- ; "Your system program should place in the RESET vector the
- ; address of a routine that ... closes the files."
- ldx #<_exit
- lda #>_exit
- jsr reset ; Setup RESET vector
-
; Check for ProDOS.
ldy $BF00 ; MLI call entry point
cpy #$4C ; Is MLI present? (JMP opcode)
: sta sp
stx sp+1
+ ; ProDOS TechRefMan, chapter 5.3.5:
+ ; "Your system program should place in the RESET vector the
+ ; address of a routine that ... closes the files."
+ ldx #<_exit
+ lda #>_exit
+ jsr reset ; Setup RESET vector
+
; Call the module constructors.
jsr initlib
- ; Switch in LC bank 2 for R/O.
+ ; Switch in LC bank 2 for W/O.
+ bit $C081
+ bit $C081
+
+ ; Set the source start address.
+ ; Aka __LC_LOAD__ iff segment LC exists.
+ lda #<(__ONCE_LOAD__ + __ONCE_SIZE__)
+ ldy #>(__ONCE_LOAD__ + __ONCE_SIZE__)
+ sta $9B
+ sty $9C
+
+ ; Set the source last address.
+ ; Aka __LC_LOAD__ + __LC_SIZE__ iff segment LC exists.
+ lda #<((__ONCE_LOAD__ + __ONCE_SIZE__) + (__LC_LAST__ - __LC_START__))
+ ldy #>((__ONCE_LOAD__ + __ONCE_SIZE__) + (__LC_LAST__ - __LC_START__))
+ sta $96
+ sty $97
+
+ ; Set the destination last address.
+ ; Aka __LC_RUN__ + __LC_SIZE__ iff segment LC exists.
+ lda #<__LC_LAST__
+ ldy #>__LC_LAST__
+ sta $94
+ sty $95
+
+ ; Call into Applesoft Block Transfer Up -- which handles zero-
+ ; sized blocks well -- to move the content of the LC memory area.
+ jsr $D39A ; BLTU2
+
+ ; Switch in LC bank 2 for R/O and return.
bit $C080
+ rts
- ; Push the command-line arguments; and, call main().
- jmp callmain
+; ------------------------------------------------------------------------
.code
.byte $65 ; Quit
.word q_param
+; ------------------------------------------------------------------------
+
.rodata
; MLI parameter list for quit
.byte $00 ; reserved
.word $0000 ; reserved
+; ------------------------------------------------------------------------
+
.data
; Final jump when we're done
done: jmp DOSWARM ; Potentially patched at runtime
- .segment "INITBSS"
-
-zpsave: .res zpspace
+; ------------------------------------------------------------------------
- .bss
+ .segment "INIT"
+zpsave: .res zpspace
rvsave: .res 3
;
.export _cvlinexy, _cvline, cvlinedirect
- .import popa, _gotoxy, putchar, newline
+ .import gotoxy, putchar, newline
.include "zeropage.inc"
_cvlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline
_cvline:
.endif
cvlinedirect:
+ stx tmp1
cmp #$00 ; Is the length zero?
beq done ; Jump if done
- sta tmp1
-: txa ; Screen code
+ sta tmp2
+: lda tmp1 ; Screen code
jsr putchar ; Write, no cursor advance
jsr newline ; Advance cursor to next line
- dec tmp1
+ dec tmp2
bne :-
done: rts
--- /dev/null
+;
+; Oliver Schmidt, 2016-06-05
+;
+; unsigned char doesclrscrafterexit (void);
+;
+
+ .export _doesclrscrafterexit
+ .import done
+
+ .include "apple2.inc"
+
+_doesclrscrafterexit:
+ ; If the page we jump to when done equals the page
+ ; of the warmstart vector we'll return to BASIC so
+ ; there's no implicit clrscr() after exit().
+ lda done+2
+ sec
+ sbc #>DOSWARM
+
+ ldx #>$0000
+ rts
; - Apple II ProDOS 8 TechNote #23, ProDOS 8 Changes and Minutia
; - ProDOS TechRefMan, chapter 5.2.4
- .segment "INIT"
+ .segment "ONCE"
initdostype:
lda $BF00
: sta __dos_type
done: rts
- .bss
+ .data
-__dos_type: .res 1
+__dos_type: .byte $00
; Check for startup filename support
; ProDOS TechRefMan, chapter 5.1.5.1:
; "$2000 is a jump instruction. $2003 and $2004 are $EE."
-system: lda $2000
- cmp #$4C
+system: lda #$4C
+ cmp $2000
bne jump
- lda $2003
- cmp #$EE
+ lda #$EE
+ cmp $2003
bne jump
- lda $2004
- cmp #$EE
+ cmp $2004
bne jump
; Store cmdline in startup filename buffer
;
.export __EXEHDR__ : absolute = 1 ; Linker referenced
- .import __LOADADDR__, __LOADSIZE__ ; Linker generated
+ .import __MAIN_START__, __MAIN_LAST__ ; Linker generated
; ------------------------------------------------------------------------
.segment "EXEHDR"
- .addr __LOADADDR__ ; Load address
- .word __LOADSIZE__ ; Load length
+ .addr __MAIN_START__ ; Load address
+ .word __MAIN_LAST__ - __MAIN_START__ ; Load length
.include "errno.inc"
.include "../filedes.inc"
- .segment "INIT"
+ .segment "ONCE"
initiobuf:
; Convert end address highbyte to table index
; ------------------------------------------------------------------------
- .bss
+ .data
table: .res MAX_FDS
; Identify machine according to:
; Apple II Miscellaneous TechNote #7, Apple II Family Identification
- .segment "INIT"
+ .segment "ONCE"
initostype:
sec
ldx #$00
rts
- .bss
+ .segment "INIT"
ostype: .res 1
; void __fastcall__ gotox (unsigned char x);
;
- .export _gotoxy, _gotox
+ .export gotoxy, _gotoxy, _gotox
.import popa, VTABZ
.include "apple2.inc"
+gotoxy:
+ jsr popa ; Get Y
+
_gotoxy:
clc
adc WNDTOP
.include "apple2.inc"
- .segment "INIT"
+ .macpack apple2
+
+ .segment "ONCE"
initirq:
; Check for ProDOS
jmp _exit
errmsg: .ifdef __APPLE2ENH__
- .byte $8D, 't'|$80, 'p'|$80, 'u'|$80, 'r'|$80, 'r'|$80
- .byte 'e'|$80, 't'|$80, 'n'|$80, 'i'|$80, ' '|$80, 'c'|$80
- .byte 'o'|$80, 'l'|$80, 'l'|$80, 'a'|$80, ' '|$80, 'o'|$80
- .byte 't'|$80, ' '|$80, 'd'|$80, 'e'|$80, 'l'|$80, 'i'|$80
- .byte 'a'|$80, 'F'|$80, $8D
+ scrcode $0D, "tpurretni colla ot deliaF", $0D
.else
- .byte $8D, 'T'|$80, 'P'|$80, 'U'|$80, 'R'|$80, 'R'|$80
- .byte 'E'|$80, 'T'|$80, 'N'|$80, 'I'|$80, ' '|$80, 'C'|$80
- .byte 'O'|$80, 'L'|$80, 'L'|$80, 'A'|$80, ' '|$80, 'O'|$80
- .byte 'T'|$80, ' '|$80, 'D'|$80, 'E'|$80, 'L'|$80, 'I'|$80
- .byte 'A'|$80, 'F'|$80, $8D
+ scrcode $0D, "TPURRETNI COLLA OT DELIAF", $0D
.endif
msglen = * - errmsg
FNAM = $281
REM = $B2 ; BASIC token-code
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run.
- .segment "INIT"
+ .segment "ONCE"
initmainargs:
; destroyed.
ldy #$00
+ sty buffer + BUF_LEN - 1
: lda BASIC_BUF,x
sta buffer,y
inx
stx __argv+1
rts
-; This array is zeroed before initmainargs is called.
-; char* argv[MAXARGS+1] = {FNAM};
-
.data
+; char* argv[MAXARGS+1] = {FNAM};
+
argv: .addr FNAM
.res MAXARGS * 2
- .bss
+ .segment "INIT"
buffer: .res BUF_LEN
.include "mli.inc"
.include "filedes.inc"
- .segment "INIT"
+ .segment "ONCE"
raisefilelevel:
; Raise file level
.byte $47, EEXIST ; Duplicate filename
.byte $48, ENOSPC ; Volume full
.byte $49, ENOSPC ; Volume directory full
-; .byte $4A, EUNKNOWN ; Incompatible file format
+ .byte $4A, ENOEXEC ; Incompatible file format
.byte $4B, EINVAL ; Unsupported storage_type
; .byte $4C, EUNKNOWN ; End of file encountered
.byte $4D, ESPIPE ; Position out of range
.include "filedes.inc"
.include "apple2.inc"
- .segment "INIT"
+ .segment "ONCE"
initprompt:
; Set prompt <> ']' to let DOS 3.3 know that we're
_rebootafterexit := return
- .segment "INIT"
+ .segment "ONCE"
initreboot:
; Quit to PWRUP
../libwrk/$(TARGET)/loader.o: $(SRCDIR)/targetutil/loader.s | ../libwrk/$(TARGET)
$(ASSEMBLE_recipe)
-../targetutil/loader.system: ../libwrk/$(TARGET)/loader.o $(SRCDIR)/targetutil/loader.cfg | ../targetutil
+../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): ../targetutil/loader.system
+$(TARGET): ../target/$(TARGET)/util/loader.system
.include "zeropage.inc"
.include "apple2.inc"
-WIDTH = tmp2
-HEIGHT = tmp3
-XORIGIN = tmp4
-YORIGIN = ptr1
+WIDTH = ptr1
+HEIGHT = ptr1+1
+XORIGIN = ptr2
+YORIGIN = ptr2+1
_textframexy:
sec
.import start
.export _cas_init
-.segment "INIT"
+.segment "ONCE"
_cas_init:
.ifdef DEBUG
;
.export _cclearxy, _cclear
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1
_cclearxy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cclear
_cclear:
;
.export _chlinexy, _chline
- .import popa, _gotoxy, cputdirect, setcursor
+ .import gotoxy, cputdirect, setcursor
.importzp tmp1
.ifdef __ATARI5200__
_chlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_chline:
.export _cputcxy, _cputc
.export plot, cputdirect, putchar
- .import popa, _gotoxy, mul40
+ .import gotoxy, mul40
.importzp tmp4,ptr4
.import _revflag,setcursor
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
_cputc:
;
.export __STARTUP__ : absolute = 1 ; Mark as startup
- .export _exit, start
+ .export _exit, start, excexit, SP_save
.import initlib, donelib
.import callmain, zerobss
.import __RESERVED_MEMORY__
- .import __RAM_START__, __RAM_SIZE__
+ .import __MAIN_START__, __MAIN_SIZE__
.ifdef __ATARIXL__
.import __STACKSIZE__
.import sram_init
.ifdef __ATARIXL__
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
- lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp+1
+ stx sp+1
.else
; Report the memory usage.
lda APPMHI
+ ldx APPMHI+1
sta APPMHI_save ; remember old APPMHI value
- lda APPMHI+1
- sta APPMHI_save+1
+ stx APPMHI_save+1
sec
lda MEMTOP
; Call the module destructors. This is also the exit() entry.
-_exit: jsr donelib ; Run module destructors
+_exit: ldx SP_save
+ txs ; Restore stack pointer
; Restore the system stuff.
- ldx SP_save
- txs ; Restore stack pointer
+excexit:jsr donelib ; Run module destructors; 'excexit' is called from the exec routine
; Restore the left margin.
; Restore APPMHI.
lda APPMHI_save
+ ldx APPMHI_save+1
sta APPMHI
- lda APPMHI_save+1
- sta APPMHI+1
+ stx APPMHI+1
.ifdef __ATARIXL__
lda RAMTOP_save
sta RAMTOP
lda MEMTOP_save
+ ldx MEMTOP_save+1
sta MEMTOP
- lda MEMTOP_save+1
- sta MEMTOP+1
+ stx MEMTOP+1
; Issue a GRAPHICS 0 call (copied'n'pasted from the TGI drivers), in
.include "atari.inc"
.export _cvlinexy, _cvline
- .import popa, _gotoxy, putchar, setcursor
+ .import gotoxy, putchar, setcursor
.importzp tmp1
.ifdef __ATARI5200__
_cvlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline
_cvline:
--- /dev/null
+;
+; Christian Groessler, June-2016
+;
+; unsigned char doesclrscr(void);
+;
+; returns 0/1 if after program termination the screen isn't/is cleared
+;
+
+ .export _doesclrscrafterexit
+ .import __is_cmdline_dos
+ .import return1
+
+.ifdef __ATARIXL__
+_doesclrscrafterexit = return1 ; the c65 runtime always clears the screen at program termination
+.else
+_doesclrscrafterexit:
+ jsr __is_cmdline_dos ; currently (unless a DOS behaving differently is popping up)
+ eor #$01 ; we can get by with the inverse of __is_cmdline_dos
+ rts
+.endif
; ------------------------------------------------------------------------
; DOS type detection
-.segment "INIT"
+.segment "ONCE"
detect: lda DOS
cmp #'S' ; SpartaDOS
; ------------------------------------------------------------------------
; Data
- .bss
+ .data
-__dos_type: .res 1 ; default to ATARIDOS
+__dos_type: .byte ATARIDOS; default to ATARIDOS
--- /dev/null
+;
+; Christian Groessler, 12-Jun-2016
+;
+; int __fastcall__ exec (const char* progname, const char* cmdline);
+;
+; supports only XDOS at the moment
+
+ .export _exec
+
+ .import popax
+ .import __dos_type
+ .import findfreeiocb
+ .import incsp2
+ .import excexit ; from crt0.s
+ .import SP_save ; from crt0.s
+.ifdef UCASE_FILENAME
+ .import ucase_fn
+ .import addysp
+.endif
+
+ .include "zeropage.inc"
+ .include "errno.inc"
+ .include "atari.inc"
+
+; area $0100 to $0128 might be in use (e.g. Hias' high speed patch)
+CMDLINE_BUFFER = $0129 ; put progname + cmdline as one single string there
+; alternatively:
+;CMDLINE_BUFFER = $0480 ; put progname + cmdline as one single string there
+CMDLINE_MAX = 40+3 ; max. length of drive + progname + cmdline
+
+ .code
+
+notsupp:lda #ENOSYS ; "unsupported system call"
+ .byte $2C ; bit opcode, eats the next 2 bytes
+noiocb: lda #EMFILE ; "too many open files"
+ jsr incsp2 ; clean up stack
+seterr: jmp __directerrno
+
+
+; entry point
+
+_exec:
+ ; save cmdline
+ sta ptr3
+ stx ptr3+1
+
+ ldy __dos_type
+ cpy #XDOS
+ bne notsupp
+
+ jsr findfreeiocb
+ bne noiocb
+
+ stx tmp4 ; remember IOCB index
+
+ ; get program name
+ jsr popax
+
+.ifdef UCASE_FILENAME
+.ifdef DEFAULT_DEVICE
+ ldy #$80
+.else
+ ldy #$00
+.endif
+ sty tmp2 ; set flag for ucase_fn
+ jsr ucase_fn
+ bcc ucok1
+invret: lda #EINVAL ; file name is too long
+ bne seterr
+ucok1:
+.endif ; defined UCASE_FILENAME
+
+; copy program name and arguments to CMDLINE_BUFFER
+
+ sta ptr4 ; ptr4: pointer to program name
+ stx ptr4+1
+ ldy #0
+ ; TODO: check stack ptr and and use min(CMDLINE_MAX,available_stack)
+copyp: lda (ptr4),y
+ beq copypd
+ sta CMDLINE_BUFFER,y
+ iny
+ cpy #CMDLINE_MAX
+ bne copyp
+
+ ; programe name too long
+ beq invret
+
+.ifndef UCASE_FILENAME
+invret: lda #EINVAL
+ bne seterr
+.endif
+
+; file name copied, check for args
+
+copypd: tya ; put Y into X (index into CMDLINE_BUFFER)
+ tax
+ lda ptr3
+ ora ptr3+1 ; do we have arguments?
+ beq copycd ; no
+ ldy #0
+ lda (ptr3),y ; get first byte of cmdline parameter
+ beq copycd ; nothing there...
+ lda #' ' ; add a space btw. progname and cmdline
+ bne copyc1
+
+; copy args
+
+copyc: lda (ptr3),y
+ beq copycd
+ iny
+copyc1: sta CMDLINE_BUFFER,x
+ inx
+ cpx #CMDLINE_MAX
+ bne copyc
+ ; progname + arguments too long
+ beq invret
+
+invexe: jsr close
+ lda #XNTBIN
+ bne setmerr
+
+copycd: lda #ATEOL
+ sta CMDLINE_BUFFER,x
+
+; open the program file, read the first two bytes and compare them to $FF
+
+ ldx tmp4 ; get IOCB index
+ lda ptr4 ; ptr4 points to progname
+ sta ICBAL,x
+ lda ptr4+1
+ sta ICBAH,x
+ lda #OPNIN ; open for input
+ sta ICAX1,x
+ lda #OPEN
+ sta ICCOM,x
+ jsr CIOV
+
+ tya
+
+.ifdef UCASE_FILENAME
+ ldy tmp3 ; get size
+ jsr addysp ; free used space on the stack
+ ; the following 'bpl' depends on 'addysp' restoring A as last command before 'rts'
+.endif ; defined UCASE_FILENAME
+
+ bpl openok
+ pha ; remember error code
+ jsr close ; close the IOCB (required even if open failed)
+ pla ; put error code back into A
+setmerr:jmp __mappederrno ; update errno from OS specific error code in A
+
+openok: lda #>buf
+ sta ICBAH,x ; set buffer address
+ lda #<buf
+ sta ICBAL,x
+ lda #0 ; set buffer length
+ sta ICBLH,x
+ lda #2
+ sta ICBLL,x
+ lda #GETCHR ; iocb command code
+ sta ICCOM,x
+ jsr CIOV ; read it
+ bmi invexe ; read operation failed, return error
+
+ lda ICBLL,x ; # of bytes read
+ cmp #2
+ bne invexe
+ lda #$FF ; check file format (need $FFFF at the beginning)
+ cmp buf
+ bne invexe
+ cmp buf+1
+ bne invexe
+
+ jsr close ; close program file
+
+; program file appears to be available and good
+; here's the point of no return
+
+ ldx SP_save
+ txs ; reset stack pointer to what it was at program entry
+ lda tmp4 ; get IOCB index
+ pha ; and save it ('excexit' calls destructors and they might destroy tmp4)
+ jsr excexit ; on atarixl this will enable the ROM again, making all high variables inaccessible
+ pla
+ tax ; IOCB index in X
+
+ lda #<CMDLINE_BUFFER
+ sta ICBAL,x ; address
+ lda #>CMDLINE_BUFFER
+ sta ICBAH,x
+ lda #0
+ sta ICBLL,x ; length shouldn't be random, but 0 is ok
+ sta ICBLH,x
+ sta ICAX1,x
+ sta ICAX2,x
+ lda #80 ; XDOS: run DUP command
+ sta ICCOM,x
+ jmp CIOV_org ; no way to display an error message in case of failure, and we will return to DOS
+
+
+; close IOCB, index in X
+.proc close
+ lda #CLOSE
+ sta ICCOM,x
+ jmp CIOV ; close IOCB
+.endproc
+
+ .bss
+
+buf: .res 2
; This file defines the EXE header and main chunk load header for Atari executables
.export __EXEHDR__: absolute = 1
- .import __RAM_START__, __BSS_LOAD__
+ .import __MAIN_START__, __BSS_LOAD__
.segment "EXEHDR"
.word $FFFF
.segment "MAINHDR"
- .word __RAM_START__
+ .word __MAIN_START__
.word __BSS_LOAD__ - 1
; startup code but is nevertheless included in the compiled program when
; needed.
+; XDOS support added 05/2016 by Christian Groessler
+
MAXARGS = 16 ; max. amount of arguments in arg. table
CL_SIZE = 64 ; command line buffer size
SPACE = 32 ; SPACE char.
; --------------------------------------------------------------------------
; Get command line
-.segment "INIT"
+.segment "ONCE"
-initmainargs:
- lda #0
- sta __argc
- sta __argc+1
- sta __argv
- sta __argv+1
+nargdos:rts
+initmainargs:
lda __dos_type ; which DOS?
- cmp #ATARIDOS
- beq nargdos ; DOS does not support arguments
- cmp #MYDOS
- bne argdos ; DOS supports arguments
-nargdos:rts
+ cmp #MAX_DOS_WITH_CMDLINE + 1
+ bcs nargdos
; Initialize ourcl buffer
-argdos: lda #ATEOL
- sta ourcl+CL_SIZE
+argdos: ldy #ATEOL
+ sty ourcl+CL_SIZE
+
+; Move SpartaDOS/XDOS command line to our own buffer
-; Move SpartaDOS command line to our own buffer
+ cmp #XDOS
+ bne sparta
- lda DOSVEC
+ lda #<XLINE
+ sta ptr1
+ lda #>XLINE
+ sta ptr1+1
+ bne cpcl0
+
+sparta: lda DOSVEC
clc
adc #<LBUF
sta ptr1
adc #>LBUF
sta ptr1+1
- ldy #0
+cpcl0: ldy #0
cpcl: lda (ptr1),y
sta ourcl,y
iny
finargs:
lda __argc
- asl
+ asl
tax
lda #0
sta argv,x
; --------------------------------------------------------------------------
; Data
-.bss
+.segment "INIT"
argv: .res (1 + MAXARGS) * 2
__getdefdev:
lda __dos_type ; which DOS?
- cmp #ATARIDOS
- beq finish
- cmp #MYDOS
- beq finish
+ cmp #XDOS
+ beq xdos ; only supported on XDOS ...
+; cmp #OSADOS+1 ; (redundant: #OSADOS+1 = #XDOS)
+ bcs finish ; ... and on OS/A+ and SpartaDOS
ldy #BUFOFF
lda #0
lda (DOSVEC),y
sta crvec+2
-crvec: jsr $FFFF ; will be set to crunch vector
+ jsr crvec
; Get default device
sta __defdev
iny
lda (DOSVEC),y
- sta __defdev+1
+done: sta __defdev+1
; Return pointer to default device
ldx #>__defdev
rts
+; XDOS default device retrieval
+
+xdos:
+
+; check XDOS version (we need >= 2.4)
+
+ lda XGLIN
+ cmp #$4C ; there needs to be a 'JMP' opcode here
+ bne finish ; older version, use DEFAULT_DEVICE or D1:
+ lda XVER ; get BCD encoded version ($24 for 2.4)
+ cmp #$24
+ bcc finish ; too old, below 2.4
+
+; good XDOS version, get default drive
+
+ lda #ATEOL
+ sta XLINE ; simulate empty command line
+ ldy #0
+ jsr XMOVE ; create an FMS filename (which in this case only contains the drive)
+ lda XFILE+1
+ bne done
+
.data
-; Default device
+crvec: jmp $FFFF ; target address will be set to crunch vector
+
+; Default device string
__defdev:
.ifdef DEFAULT_DEVICE
.else
.byte "D1:", 0
.endif
-
.include "atari.inc"
- .export _gotoxy
+ .export gotoxy, _gotoxy
.import popa
.import setcursor
+gotoxy:
+ jsr popa ; Get Y
+
_gotoxy: ; Set the cursor position
sta ROWCRS ; Set Y
jsr popa ; Get X
sta COLCRS ; Set X
lda #0
- sta COLCRS+1 ;
+ sta COLCRS+1
jmp setcursor
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda VVBLKD
--- /dev/null
+;
+; Christian Groessler, May-2016
+;
+; unsigned char _is_cmdline_dos(void);
+;
+; returns 0 for non-commandline DOS, 1 for commandline DOS
+;
+
+ .export __is_cmdline_dos
+ .import __dos_type
+ .include "atari.inc"
+
+__is_cmdline_dos:
+ lda #MAX_DOS_WITH_CMDLINE
+ cmp __dos_type
+ lda #0
+ rol a
+ rts
; ------------------------------------------------------------------------
- .segment "INIT"
+ .segment "ONCE"
pm_init:
lda #0
.include "fcntl.inc"
.include "errno.inc"
.include "fd.inc"
+ .include "zeropage.inc"
.export _open
.destructor closeallfiles, 5
.import incsp4
.import ldaxysp,addysp
.import __oserror
- .importzp tmp4,tmp2
.ifdef UCASE_FILENAME
- .importzp tmp3
.import ucase_fn
.endif
.ifdef UCASE_FILENAME
.ifdef DEFAULT_DEVICE
ldy #$80
- sty tmp2 ; set flag for ucase_fn
+.else
+ ldy #$00
.endif
+ sty tmp2 ; set flag for ucase_fn
jsr ucase_fn
bcc ucok1
invret: lda #<EINVAL ; file name is too long
.byte EUNKNOWN ; 177 - haven't found documentation
.byte EUNKNOWN ; 178 - haven't found documentation
.byte EUNKNOWN ; 179 - haven't found documentation
- .byte EUNKNOWN ; 180 - not a binary file
+ .byte ENOEXEC ; 180 - not a binary file
.byte EUNKNOWN ; 181 - [MYDOS] invalid address range
.byte EUNKNOWN ; 182 - [XDOS] invalid parameter
.export CIO_handler
.export SIO_handler
.export SETVBV_handler
+ .export XMOVE_handler
BUFSZ = 128 ; bounce buffer size
BUFSZ_SIO = 256
-.segment "INIT"
+.segment "ONCE"
; Turn off ROMs, install system and interrupt wrappers, set new chargen pointer
plp
rts
+;---------------------------------------------------------
+
+XMOVE_handler:
+
+ pha
+ lda PORTB
+ sta cur_XMOVE_PORTB
+ enable_rom
+ pla
+ jsr XMOVE_org
+ php
+ pha
+ disable_rom_val cur_XMOVE_PORTB
+ pla
+ plp
+ rts
+
+
CIO_a: .res 1
CIO_x: .res 1
CIO_y: .res 1
cur_SIOV_PORTB: .res 1
cur_KEYBDV_PORTB: .res 1
cur_SETVBV_PORTB: .res 1
+cur_XMOVE_PORTB: .res 1
orig_ptr: .res 2
orig_len: .res 2
req_len: .res 2
pha
lda __dos_type
- beq not_impl ; AtariDOS
cmp #OSADOS+1
bcc do_sparta ; OS/A and SpartaDOS
+ cmp #MYDOS
+ bne not_impl ; neither MyDOS, OS/A, nor SpartaDOS
pla
- jmp __sysremove ; MyDOS and others (TODO: check XDOS)
+ jmp __sysremove ; MyDOS
not_impl:
pla
../libwrk/$(TARGET)/w2cas.o: $(SRCDIR)/targetutil/w2cas.c | ../libwrk/$(TARGET)
$(COMPILE_recipe)
-../targetutil/w2cas.com: ../libwrk/$(TARGET)/w2cas.o ../lib/$(TARGET).lib | ../targetutil
+../target/$(TARGET)/util/w2cas.com: ../libwrk/$(TARGET)/w2cas.o ../lib/$(TARGET).lib | ../target/$(TARGET)/util
$(LD65) -o $@ -t $(TARGET) $^
-$(TARGET): ../targetutil/w2cas.com
+$(TARGET): ../target/$(TARGET)/util/w2cas.com
#include <errno.h>
#include <6502.h>
#include <atari.h>
+#include <cc65.h>
#include <conio.h>
static int verbose = 1;
struct __iocb *iocb = findfreeiocb();
int iocb_num;
+ /* if DOS will automatically clear the screen after the program exits, wait for a keypress... */
+ if (doesclrscrafterexit())
+ atexit((void (*)(void))cgetc);
+
if (! iocb) {
fprintf(stderr, "couldn't find a free iocb\n");
- if (_dos_type != 1)
- cgetc();
return 1;
}
iocb_num = (iocb - &IOCB) * 16;
printf("\nfilename: ");
x = fgets(buf, 19, stdin);
printf("\n");
- if (! x)
+ if (! x) {
+ printf("empty filename, exiting...\n");
return 1;
+ }
if (*x && *(x + strlen(x) - 1) == '\n')
*(x + strlen(x) - 1) = 0;
+ if (! strlen(x)) { /* empty filename */
+ printf("empty filename, exiting...\n");
+ return 1;
+ }
filename = x;
}
else {
buffer = malloc(buflen);
if (! buffer) {
fprintf(stderr, "cannot alloc %ld bytes -- aborting...\n", (long)buflen);
- if (_dos_type != 1)
- cgetc();
return 1;
}
}
if (! file) {
free(buffer);
fprintf(stderr, "cannot open '%s': %s\n", filename, strerror(errno));
- if (_dos_type != 1)
- cgetc();
return 1;
}
file_err:
fclose(file);
free(buffer);
- if (_dos_type != 1)
- cgetc();
return 1;
}
if (filen > 32767l) {
if (regs.y != 1) {
fprintf(stderr, "CIO call to open cassette returned %d\n", regs.y);
free(buffer);
- if (_dos_type != 1)
- cgetc();
return 1;
}
regs.pc = 0xe456; /* CIOV */
_sys(®s);
- if (_dos_type != 1)
- cgetc();
return 1;
}
if (regs.y != 1) {
fprintf(stderr, "CIO call to close cassette returned %d\n", regs.y);
- if (_dos_type != 1)
- cgetc();
return 1;
}
/* all is fine */
printf("success\n");
- if (_dos_type != 1)
- cgetc();
return 0;
}
stx ptr4+1
.ifdef DEFAULT_DEVICE
- ; bit #0 of tmp2 is used as a flag whether device name is present in passed string (1 = present, 0 = not present)
+ lda tmp2
+ beq hasdev ; don't fiddle with device part
+ ; bit #0 of tmp2 is used as an additional flag whether device name is present in passed string (1 = present, 0 = not present)
ldy #1
inc tmp2 ; initialize flag: device present
lda #':'
.ifdef DEFAULT_DEVICE
lda #1
- bit tmp2
+ bit tmp2 ; is a device present in the string?
bne hasdev2 ; yes, don't prepend something
- bpl hasdev2
+ bpl hasdev2 ; check input parameter (tmp2 != $80)
- ldy #128+3 ; no, prepend "D:" (or other device)
+ ldy #128+3 ; no, prepend "Dn:" (__defdev)
sty tmp3 ; adjust stack size used
ldy #3
jsr subysp ; adjust stack pointer
--- /dev/null
+; Atari VCS 2600 startup code for cc65
+;
+; Florent Flament (contact@florentflament.com), 2017
+
+ .export _exit
+ .export __STARTUP__ : absolute = 1
+
+ .import __RAM_START__, __RAM_SIZE__
+ .import copydata
+ .import _main
+
+ .include "zeropage.inc"
+
+
+.segment "STARTUP"
+start:
+; Clear decimal mode
+ cld
+
+; Initialization Loop:
+; * Clears Atari 2600 whole memory (128 bytes) including BSS segment
+; * Clears TIA registers
+; * Sets system stack pointer to $ff (i.e top of zero-page)
+ ldx #0
+ txa
+clearLoop:
+ dex
+ txs
+ pha
+ bne clearLoop
+
+; Initialize data
+ jsr copydata
+
+; Initialize C stack pointer
+ lda #<(__RAM_START__ + __RAM_SIZE__)
+ ldx #>(__RAM_START__ + __RAM_SIZE__)
+ sta sp
+ stx sp+1
+
+; Call main
+ jsr _main
+_exit: jmp _exit
+
+
+.segment "VECTORS"
+.word start ; NMI
+.word start ; Reset
+.word start ; IRQ
--- /dev/null
+;
+; Ullrich von Bassewitz, 2003-10-10
+;
+; Character specification table.
+;
+
+ .include "ctype.inc"
+
+; The tables are readonly, put them into the rodata segment
+
+.rodata
+
+; The following 256 byte wide table specifies attributes for the isxxx type
+; of functions. Doing it by a table means some overhead in space, but it
+; has major advantages:
+;
+; * It is fast. If it weren't for the slow parameter passing of cc65, one
+; could even define macros for the isxxx functions (this is usually
+; done on other platforms).
+;
+; * It is highly portable. The only unportable part is the table itself,
+; all real code goes into the common library.
+;
+; * We save some code in the isxxx functions.
+
+
+__ctype:
+ .byte CT_CTRL ; 0/00 ___ctrl_@___
+ .byte CT_CTRL ; 1/01 ___ctrl_A___
+ .byte CT_CTRL ; 2/02 ___ctrl_B___
+ .byte CT_CTRL ; 3/03 ___ctrl_C___
+ .byte CT_CTRL ; 4/04 ___ctrl_D___
+ .byte CT_CTRL ; 5/05 ___ctrl_E___
+ .byte CT_CTRL ; 6/06 ___ctrl_F___
+ .byte CT_CTRL ; 7/07 ___ctrl_G___
+ .byte CT_CTRL ; 8/08 ___ctrl_H___
+ .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB
+ ; 9/09 ___ctrl_I___
+ .byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___
+ .byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___
+ .byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___
+ .byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___
+ .byte CT_CTRL ; 14/0e ___ctrl_N___
+ .byte CT_CTRL ; 15/0f ___ctrl_O___
+ .byte CT_CTRL ; 16/10 ___ctrl_P___
+ .byte CT_CTRL ; 17/11 ___ctrl_Q___
+ .byte CT_CTRL ; 18/12 ___ctrl_R___
+ .byte CT_CTRL ; 19/13 ___ctrl_S___
+ .byte CT_CTRL ; 20/14 ___ctrl_T___
+ .byte CT_CTRL ; 21/15 ___ctrl_U___
+ .byte CT_CTRL ; 22/16 ___ctrl_V___
+ .byte CT_CTRL ; 23/17 ___ctrl_W___
+ .byte CT_CTRL ; 24/18 ___ctrl_X___
+ .byte CT_CTRL ; 25/19 ___ctrl_Y___
+ .byte CT_CTRL ; 26/1a ___ctrl_Z___
+ .byte CT_CTRL ; 27/1b ___ctrl_[___
+ .byte CT_CTRL ; 28/1c ___ctrl_\___
+ .byte CT_CTRL ; 29/1d ___ctrl_]___
+ .byte CT_CTRL ; 30/1e ___ctrl_^___
+ .byte CT_CTRL ; 31/1f ___ctrl_____
+ .byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___
+ .byte CT_NONE ; 33/21 _____!_____
+ .byte CT_NONE ; 34/22 _____"_____
+ .byte CT_NONE ; 35/23 _____#_____
+ .byte CT_NONE ; 36/24 _____$_____
+ .byte CT_NONE ; 37/25 _____%_____
+ .byte CT_NONE ; 38/26 _____&_____
+ .byte CT_NONE ; 39/27 _____'_____
+ .byte CT_NONE ; 40/28 _____(_____
+ .byte CT_NONE ; 41/29 _____)_____
+ .byte CT_NONE ; 42/2a _____*_____
+ .byte CT_NONE ; 43/2b _____+_____
+ .byte CT_NONE ; 44/2c _____,_____
+ .byte CT_NONE ; 45/2d _____-_____
+ .byte CT_NONE ; 46/2e _____._____
+ .byte CT_NONE ; 47/2f _____/_____
+ .byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____
+ .byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____
+ .byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____
+ .byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____
+ .byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____
+ .byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____
+ .byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____
+ .byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____
+ .byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____
+ .byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____
+ .byte CT_NONE ; 58/3a _____:_____
+ .byte CT_NONE ; 59/3b _____;_____
+ .byte CT_NONE ; 60/3c _____<_____
+ .byte CT_NONE ; 61/3d _____=_____
+ .byte CT_NONE ; 62/3e _____>_____
+ .byte CT_NONE ; 63/3f _____?_____
+
+ .byte CT_NONE ; 64/40 _____@_____
+ .byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____
+ .byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____
+ .byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____
+ .byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____
+ .byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____
+ .byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____
+ .byte CT_UPPER ; 71/47 _____G_____
+ .byte CT_UPPER ; 72/48 _____H_____
+ .byte CT_UPPER ; 73/49 _____I_____
+ .byte CT_UPPER ; 74/4a _____J_____
+ .byte CT_UPPER ; 75/4b _____K_____
+ .byte CT_UPPER ; 76/4c _____L_____
+ .byte CT_UPPER ; 77/4d _____M_____
+ .byte CT_UPPER ; 78/4e _____N_____
+ .byte CT_UPPER ; 79/4f _____O_____
+ .byte CT_UPPER ; 80/50 _____P_____
+ .byte CT_UPPER ; 81/51 _____Q_____
+ .byte CT_UPPER ; 82/52 _____R_____
+ .byte CT_UPPER ; 83/53 _____S_____
+ .byte CT_UPPER ; 84/54 _____T_____
+ .byte CT_UPPER ; 85/55 _____U_____
+ .byte CT_UPPER ; 86/56 _____V_____
+ .byte CT_UPPER ; 87/57 _____W_____
+ .byte CT_UPPER ; 88/58 _____X_____
+ .byte CT_UPPER ; 89/59 _____Y_____
+ .byte CT_UPPER ; 90/5a _____Z_____
+ .byte CT_NONE ; 91/5b _____[_____
+ .byte CT_NONE ; 92/5c _____\_____
+ .byte CT_NONE ; 93/5d _____]_____
+ .byte CT_NONE ; 94/5e _____^_____
+ .byte CT_NONE ; 95/5f _UNDERLINE_
+ .byte CT_NONE ; 96/60 ___grave___
+ .byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____
+ .byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____
+ .byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____
+ .byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____
+ .byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____
+ .byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____
+ .byte CT_LOWER ; 103/67 _____g_____
+ .byte CT_LOWER ; 104/68 _____h_____
+ .byte CT_LOWER ; 105/69 _____i_____
+ .byte CT_LOWER ; 106/6a _____j_____
+ .byte CT_LOWER ; 107/6b _____k_____
+ .byte CT_LOWER ; 108/6c _____l_____
+ .byte CT_LOWER ; 109/6d _____m_____
+ .byte CT_LOWER ; 110/6e _____n_____
+ .byte CT_LOWER ; 111/6f _____o_____
+ .byte CT_LOWER ; 112/70 _____p_____
+ .byte CT_LOWER ; 113/71 _____q_____
+ .byte CT_LOWER ; 114/72 _____r_____
+ .byte CT_LOWER ; 115/73 _____s_____
+ .byte CT_LOWER ; 116/74 _____t_____
+ .byte CT_LOWER ; 117/75 _____u_____
+ .byte CT_LOWER ; 118/76 _____v_____
+ .byte CT_LOWER ; 119/77 _____w_____
+ .byte CT_LOWER ; 120/78 _____x_____
+ .byte CT_LOWER ; 121/79 _____y_____
+ .byte CT_LOWER ; 122/7a _____z_____
+ .byte CT_NONE ; 123/7b _____{_____
+ .byte CT_NONE ; 124/7c _____|_____
+ .byte CT_NONE ; 125/7d _____}_____
+ .byte CT_NONE ; 126/7e _____~_____
+ .byte CT_OTHER_WS ; 127/7f ____DEL____
+
+ .res 128, CT_NONE ; 128-255
+
+
+
;
; Christian Groessler, 01-Mar-2014
-.include "atari.mac"
-
.export __CART_NAME__: absolute = 1
+.macpack atari
+
.segment "CARTNAME"
scrcode " cc"
.export screen_setup_20x24
- .segment "INIT"
+ .segment "ONCE"
screen_setup_20x24:
.export _cputcxy, _cputc
.export plot, cputdirect, putchar
- .import popa, _gotoxy, mul20
+ .import gotoxy, mul20
.importzp ptr4
.import setcursor
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
_cputc:
; Set up the stack.
lda #<(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__)
+ ldx #>(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__)
sta sp
- lda #>(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__)
- sta sp+1 ; Set argument stack ptr
+ stx sp+1 ; Set argument stack ptr
; Call the module constructors.
.include "atari5200.inc"
- .export _gotoxy
+ .export gotoxy, _gotoxy
.import popa
.import setcursor
+gotoxy:
+ jsr popa ; Get Y
+
_gotoxy: ; Set the cursor position
sta ROWCRS_5200 ; Set Y
jsr popa ; Get X
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda VVBLKD
;
; 2010-11-14, Ullrich von Bassewitz
-; 2014-09-06, Greg King
+; 2016-03-17, Greg King
;
; This module supplies a small BASIC stub program that uses CALL
; to jump to the machine-language code that follows it.
.byte $00 ; End of BASIC line
Next: .addr $0000 ; BASIC program end marker
Start:
+
+; ------------------------------------------------------------------------
+
+; This padding is needed by a bug in the ROM.
+; (The CLOAD command starts BASIC's variables table on top of the last byte
+; that was loaded [instead of at the next address].)
+
+.segment "BASTAIL"
+
+ .byte 0
;--------------------------------------------------------------------------
-; Put this constructor into a segment that can be re-used by programs.
+; Put this constructor into a segment whose space
+; will be re-used by BSS, the heap, and the C stack.
;
-.segment "INIT"
+.segment "ONCE"
; Turn the capitals lock off.
;--------------------------------------------------------------------------
-.bss
+.segment "INIT"
capsave:
.res 1
.endproc
; ------------------------------------------------------------------------
-; Switch the cursor off. Code goes into the INIT segment
-; which may be reused after it is run.
+; Switch the cursor off. Code goes into the ONCE segment,
+; which will be reused after it is run.
-.segment "INIT"
+.segment "ONCE"
initcgetc:
lsr STATUS
; Startup code for cc65 (Oric version)
;
; By Debrune Jérôme <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org>
-; 2015-01-09, Greg King
+; 2016-03-18, Greg King
;
.export _exit
.export __STARTUP__ : absolute = 1 ; Mark as startup
+
.import initlib, donelib
.import callmain, zerobss
- .import __RAM_START__, __RAM_SIZE__, __STACKSIZE__
+ .import __MAIN_START__, __MAIN_SIZE__
.include "zeropage.inc"
.include "atmos.inc"
.segment "STARTUP"
-; Save the zero-page area that we're about to use.
-
- ldx #zpspace-1
-L1: lda sp,x
- sta zpsave,x
- dex
- bpl L1
-
-; Clear the BSS data.
-
- jsr zerobss
-
-; Currently, color isn't supported on the text screen.
-; Unprotect screen columns 0 and 1 (where each line's color codes would sit).
-
- lda STATUS
- sta stsave
- and #%11011111
- sta STATUS
-
-; Save some system stuff; and, set up the stack.
-
tsx
stx spsave ; Save system stk ptr
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp
- lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp+1 ; Set argument stack ptr
+; Save space by putting some of the start-up code in a segment
+; that will be re-used.
-; Call the module constructors.
+ jsr init
- jsr initlib
+; Clear the BSS variables (after the constructors have been run).
+
+ jsr zerobss
; Push the command-line arguments; and, call main().
; Copy back the zero-page stuff.
- ldx #zpspace-1
+ ldx #zpspace - 1
L2: lda zpsave,x
sta sp,x
dex
rts
; ------------------------------------------------------------------------
+; Put this code in a place that will be re-used by BSS, the heap,
+; and the C stack.
-.segment "ZPSAVE1"
+.segment "ONCE"
-zpsave:
+; Save the zero-page area that we're about to use.
-; This padding is needed by a bug in the ROM.
-; (The CLOAD command starts BASIC's variables table on top of the last byte
-; that was loaded [instead of at the next address].)
-; This is overlaid on a buffer, so that it doesn't use extra space in RAM.
+init: ldx #zpspace - 1
+L1: lda sp,x
+ sta zpsave,x
+ dex
+ bpl L1
- .byte 0
+; Currently, color isn't supported on the text screen.
+; Unprotect screen columns 0 and 1 (where each line's color codes would sit).
-; The segments "ZPSAVE1" and "ZPSAVE2" always must be together.
-; They create a single object (the zpsave buffer).
+ lda STATUS
+ sta stsave
+ and #%11011111
+ sta STATUS
-.segment "ZPSAVE2"
+; Set up the C stack.
+
+ lda #<(__MAIN_START__ + __MAIN_SIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__)
+ sta sp
+ stx sp+1 ; Set argument stack ptr
+
+; Call the module constructors.
- .res zpspace - 1
+ jmp initlib
; ------------------------------------------------------------------------
-.bss
+.segment "INIT"
spsave: .res 1
stsave: .res 1
+zpsave: .res zpspace
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda IRQVec
.macpack generic
MAXARGS = 10 ; Maximum number of arguments allowed
-REM = $9d ; BASIC token-code
+REM = $9D ; BASIC token-code
;---------------------------------------------------------------------------
-; Get possible command-line arguments. Goes into the special INIT segment,
-; which may be reused after the startup code is run
+; Get possible command-line arguments. Goes into the special ONCE segment,
+; which will be reused after the startup code is run.
-.segment "INIT"
+.segment "ONCE"
.proc initmainargs
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
-; Because the buffer, that we're copying into, was zeroed out,
-; we don't need to add a NUL character.
-;
- ldy #FNAME_LEN - 1 ; limit the length
+
+ ldy #FNAME_LEN ; Limit the length
+ lda #0 ; The terminating NUL character
+ beq L1 ; Branch always
L0: lda CFOUND_NAME,y
- sta name,y
+L1: sta name,y
dey
bpl L0
inc __argc ; argc always is equal to, at least, 1
; Find the "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- beq done ; no "rem", no args.
+ beq done ; No "rem", no args.
inx
cmp #REM
bne L2
beq done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. This is useful since we
txa ; Get low byte
add #<args
- sta argv,y ; argv[y]= &arg
+ sta argv,y ; argv[y]=&arg
lda #>$0000
adc #>args
sta argv+1,y
; A contains the terminating character. To make the argument a valid C string,
; replace the terminating character by a zero.
- lda #$00
+ lda #0
sta args-1,x
; Check if the maximum number of command line arguments is reached. If not,
.endproc
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+.segment "INIT"
+
term: .res 1
name: .res FNAME_LEN + 1
args: .res SCREEN_XSIZE * 2 - 1
.data
+
+; This array has zeroes when initmainargs starts.
+; char* argv[MAXARGS+1]={name};
+
argv: .addr name
- .res MAXARGS * 2, $00
+ .res MAXARGS * 2
;--------------------------------------------------------------------------
; initstdin: Reset the stdin console.
-.segment "INIT"
+.segment "ONCE"
initstdin:
ldx #<-1
;--------------------------------------------------------------------------
-.bss
+.segment "INIT"
text_count:
.res 1
-
;
; Based on code by Debrune Jérôme <jede@oric.org>
-; 2015-01-08, Greg King
+; 2016-03-17, Greg King
;
; The following symbol is used by the linker config. file
.export __TAPEHDR__:abs = 1
; These symbols, also, come from the configuration file.
- .import __BASHDR_LOAD__, __ZPSAVE1_LOAD__, __AUTORUN__, __PROGFLAG__
+ .import __AUTORUN__, __PROGFLAG__
+ .import __BASHEAD_START__, __MAIN_LAST__
; ------------------------------------------------------------------------
.segment "TAPEHDR"
- .byte $16, $16, $16 ; Sync bytes
- .byte $24 ; Beginning-of-header marker
+ .byte $16, $16, $16 ; Sync bytes
+ .byte $24 ; Beginning-of-header marker
- .byte $00 ; $2B0
- .byte $00 ; $2AF
- .byte <__PROGFLAG__ ; $2AE Language flag ($00=BASIC, $80=machine code)
- .byte <__AUTORUN__ ; $2AD Auto-run flag ($C7=run, $00=only load)
- .dbyt __ZPSAVE1_LOAD__ ;$2AB Address of end of file
- .dbyt __BASHDR_LOAD__ ; $2A9 Address of start of file
- .byte $00 ; $2A8
+ .byte $00 ; $2B0
+ .byte $00 ; $2AF
+ .byte <__PROGFLAG__ ; $2AE Language flag ($00=BASIC, $80=machine code)
+ .byte <__AUTORUN__ ; $2AD Auto-run flag ($C7=run, $00=only load)
+ .dbyt __MAIN_LAST__ - 1 ; $2AB Address of end of file
+ .dbyt __BASHEAD_START__ ; $2A9 Address of start of file
+ .byte $00 ; $2A8
; File name (a maximum of 17 characters), zero-terminated
.asciiz .sprintf("%u", .time)
;--------------------------------------------------------------------------
; Module constructor/destructor
-.bss
+.segment "INIT"
keyvec: .res 2
-.segment "INIT"
+.segment "ONCE"
initcgetc:
; Save the old vector
lda KeyStoreVec
+ ldx KeyStoreVec+1
sta keyvec
- lda KeyStoreVec+1
- sta keyvec+1
+ stx keyvec+1
; Set the new vector. I can only hope that this works for other C128
; versions...
stx KeyStoreVec+1
cli
rts
-
-
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.import PLOT
.include "c128.inc"
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
.import zerobss
.import push0, callmain
.import RESTOR, BSOUT, CLRCH
- .import __RAM_START__, __RAM_SIZE__, __STACKSIZE__
+ .import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__
.importzp ST
.include "zeropage.inc"
tsx
stx spsave ; Save the system stack pointer
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
- lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp+1 ; Set argument stack ptr
+ stx sp+1 ; Set argument stack ptr
; Call the module constructors.
; ------------------------------------------------------------------------
; Data
-.segment "INITBSS"
+.segment "INIT"
zpsave: .res zpspace
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda IRQVec
REM = $8f ; BASIC token-code
NAME_LEN = 16 ; Maximum length of command-name
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
-.segment "INIT"
+.segment "ONCE"
initmainargs:
stx __argv + 1
rts
-.segment "INITBSS"
+.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
; --------------------------------------------------------------------------
; Initialize the mouse sprite.
-.segment "INIT"
+.segment "ONCE"
initmcb:
; Constructor that writes to the 1/10 sec register of the TOD to kick it
; into action. If this is not done, the clock hangs. We will read the register
; and write it again, ignoring a possible change in between.
-.segment "INIT"
+.segment "ONCE"
.proc initsystime
.constructor initkbd
.destructor donekbd
-.segment "INIT"
+.segment "ONCE"
.proc initkbd
.endproc
+fnkeys: .byte $01, $01, $01, $01, $01, $01, $01, $01
+ .byte 133, 137, 134, 138, 135, 139, 136, 140
+
.code
rts
.endproc
-
-
-; Function key table, readonly
-
-.rodata
-fnkeys: .byte $01, $01, $01, $01, $01, $01, $01, $01
- .byte 133, 137, 134, 138, 135, 139, 136, 140
-
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.import PLOT
.include "plus4.inc"
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
; ------------------------------------------------------------------------
-.segment "INITBSS"
+.segment "INIT"
zpsave: .res zpspace
-;
-; Ullrich von Bassewitz, 2002-12-03
-;
-; unsigned char __fastcall__ get_tv (void);
-; /* Return the video mode the machine is using */
-;
-
- .include "plus4.inc"
- .include "get_tv.inc"
-
-
-;--------------------------------------------------------------------------
-; _get_tv
-
-.proc _get_tv
-
- ldx #TV::PAL ; Assume PAL
- bit TED_MULTI1 ; Test bit 6
- bvc pal
- dex ; NTSC
-pal: txa
- ldx #0
- rts
-
-.endproc
-
-
+.include "../plus4/get_tv.s"
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda IRQVec
REM = $8f ; BASIC token-code
NAME_LEN = 16 ; Maximum length of command-name
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
-.segment "INIT"
+.segment "ONCE"
initmainargs:
stx __argv + 1
rts
-.segment "INITBSS"
+.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.import PLOT
.include "c64.inc"
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import initlib, donelib
- .import moveinit, zerobss, callmain
+ .import zerobss, callmain
.import BSOUT
.import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; from configure file
Start:
-; Switch to the second charset.
-
- lda #14
- jsr BSOUT
-
; Switch off the BASIC ROM.
lda $01
tsx
stx spsave ; Save the system stack ptr
-; Allow some re-entrancy by skipping the next task if it already was done.
-; This sometimes can let us rerun the program without reloading it.
-
- ldx move_init
- beq L0
-
-; Move the INIT segment from where it was loaded (over the bss segments)
-; into where it must be run (over the BSS segment).
-
- jsr moveinit
- dec move_init ; Set to false
-
-; Save space by putting some of the start-up code in the INIT segment,
+; Save space by putting some of the start-up code in the ONCE segment,
; which can be re-used by the BSS segment, the heap and the C stack.
-L0: jsr runinit
+ jsr init
; Clear the BSS data.
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
-runinit:
+init:
; Save the zero-page locations that we need.
; Set up the stack.
- lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
- ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__)
sta sp
stx sp+1 ; Set argument stack ptr
+; Switch to the second charset.
+
+ lda #14
+ jsr BSOUT
+
; Call the module constructors.
jmp initlib
; ------------------------------------------------------------------------
; Data
-.data
-
-; These two variables were moved out of the BSS segment, and into DATA, because
-; we need to use them before INIT is moved off of BSS, and before BSS is zeroed.
+.segment "INIT"
mmusave:.res 1
spsave: .res 1
-
-move_init:
- .byte 1
-
-.segment "INITBSS"
-
zpsave: .res zpspace
--- /dev/null
+; C64 sprite addresses for the TGI mouse pointer
+;
+; 2017-01-13, Greg King
+
+; In order to provide a visible mouse pointer during TGI's graphics mode,
+; the object file "c64-tgimousedata.o" must be linked explicitly into
+; a program file. Example:
+;
+; cl65 -t c64 -o program-file main-code.c subroutines.s c64-tgimousedata.o
+;
+; Note: Currently, a program cannot have default
+; pointers for both text and graphic modes.
+
+; The TGI graphics mode uses VIC-II's 16K bank number three.
+;
+; Address of the TGI bitmap's color RAM
+
+COLORMAP := $D000
+
+ .export mcb_spritepointer := COLORMAP + $03F8
+ .export mcb_spritememory := COLORMAP + $0400
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda IRQVec
REM = $8f ; BASIC token-code
NAME_LEN = 16 ; Maximum length of command-name
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
-.segment "INIT"
+.segment "ONCE"
initmainargs:
stx __argv + 1
rts
-.segment "INITBSS"
+.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
; --------------------------------------------------------------------------
; Initialize the mouse sprite.
-.segment "INIT"
+.segment "ONCE"
initmcb:
.export soft80_charset
- .segment "INIT"
+ .segment "ONCE"
soft80_charset:
.byte $0f,$03,$0f,$00,$0f,$07,$05,$0e
.byte $0f,$05,$0e,$0b,$0f,$0b,$0f,$0f
sta CIA2_PRA
jmp $FF5B ; Initialize video I/O
- .segment "INIT"
+ .segment "ONCE"
firstinit:
; copy charset to RAM under I/O
sei
soft80_tables_data_end:
;-------------------------------------------------------------------------------
- .segment "INITBSS"
+ .segment "INIT"
soft80_internal_cellcolor:
.res 1
soft80_internal_bgcolor:
.export soft80_newline, soft80_plot
.export soft80_checkchar
- .import popa, _gotoxy
+ .import gotoxy
.import soft80_kplot
.import soft80_internal_bgcolor, soft80_internal_cellcolor
soft80_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
sta VIC_VIDEO_ADR
rts
- .segment "INIT"
+ .segment "ONCE"
firstinit:
; copy charset to RAM under I/O
sei
soft80_tables_data_end:
;-------------------------------------------------------------------------------
- .segment "INITBSS"
+ .segment "INIT"
soft80mono_internal_cellcolor:
.res 1
soft80mono_internal_bgcolor:
.export soft80mono_cputdirect, soft80mono_putchar
.export soft80mono_newline, soft80mono_plot
- .import popa, _gotoxy
+ .import gotoxy
.import soft80mono_kplot
.import soft80mono_internal_bgcolor, soft80mono_internal_cellcolor
soft80mono_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
; Constructor that writes to the 1/10 sec register of the TOD to kick it
; into action. If this is not done, the clock hangs. We will read the register
; and write it again, ignoring a possible change in between.
-.segment "INIT"
+.segment "ONCE"
.proc initsystime
;
; Graphics driver for the 320x200x2 mode on the C64.
;
-; Based on Stephen L. Judds GRLIB code
+; Based on Stephen L. Judd's GRLIB code.
+;
+; 2017-01-13, Greg King
;
.include "zeropage.inc"
@L2: sta CBASE+$0000,y
sta CBASE+$0100,y
sta CBASE+$0200,y
- sta CBASE+$0300,y
+ sta CBASE+$02e8,y
iny
bne @L2
pla
OUTTEXT:
; Calculate a pointer to the representation of the character in the
-; character ROM
+; character ROM
ldx #((>(CHARROM + $0800)) >> 3)
ldy #0
lda #00
@L9: sta INRANGE
rts
-
-
--- /dev/null
+;
+; 2016-08-07, Greg King
+;
+; void cbm_k_scnkey (void);
+;
+
+ .import SCNKEY
+ .export _cbm_k_scnkey := SCNKEY
--- /dev/null
+;
+; 2016-08-07, Greg King
+;
+; void cbm_k_udtim (void);
+;
+
+ .import UDTIM
+ .export _cbm_k_udtim := UDTIM
;
.export _cclearxy, _cclear
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1
_cclearxy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cclear
_cclear:
dec tmp1
bne L1
L9: rts
-
-
-
-
;
.export _chlinexy, _chline
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1, chlinechar
_chlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_chline:
dec tmp1
bne L1
L9: rts
-
-
-
-
;
.export _cvlinexy, _cvline
- .import popa, _gotoxy, putchar, newline
+ .import gotoxy, putchar, newline
.importzp tmp1, cvlinechar
_cvlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline
_cvline:
dec tmp1
bne L1
L9: rts
-
-
-
.importzp devnum
-.segment "INITBSS"
+.segment "INIT"
curunit:
.res 1
-.segment "INIT"
+.segment "ONCE"
.proc initcurunit
; void gotoxy (unsigned char x, unsigned char y);
;
- .export _gotoxy
+ .export gotoxy, _gotoxy
.import popa, plot
.importzp CURS_X, CURS_Y
+gotoxy:
+ jsr popa ; Get Y
+
_gotoxy:
sta CURS_Y ; Set Y
jsr popa ; Get X
.export _mouse_def_pointercolor
-.segment "INIT"
+.segment "ONCE"
_mouse_def_pointercolor:
.export _mouse_def_pointershape
-.segment "INIT"
+.segment "ONCE"
_mouse_def_pointershape:
;--------------------------------------------------------------------------
; initstdin: Open the stdin file descriptors for the keyboard
-.segment "INIT"
+.segment "ONCE"
.proc initstdin
;--------------------------------------------------------------------------
; initstdout: Open the stdout and stderr file descriptors for the screen.
-.segment "INIT"
+.segment "ONCE"
.proc initstdout
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.import __VIDRAM_START__
.import CURS_X: zp, CURS_Y: zp, CHARCOLOR: zp, RVS: zp
.import SCREEN_PTR: zp, CRAM_PTR: zp
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
REM = $8f ; BASIC token-code
NAME_LEN = 16 ; Maximum length of command-name
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run.
;
-.segment "INIT"
+.segment "ONCE"
initmainargs:
stx __argv + 1
rts
-.segment "INITBSS"
+.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
; --------------------------------------------------------------------------
; Initialize the mouse sprite.
-.segment "INIT"
+.segment "ONCE"
initmcb:
.export newline, plot
.destructor setsyscursor
- .import _gotoxy
- .import popa
+ .import gotoxy
.import PLOT
.import ktmp: zp, crtc: zp, CURS_X: zp, CURS_Y: zp, RVS: zp
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
REM = $8f ; BASIC token-code
NAME_LEN = 16 ; Maximum length of command-name
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run.
;
-.segment "INIT"
+.segment "ONCE"
initmainargs:
stx __argv + 1
rts
-.segment "INITBSS"
+.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
cwd_init := initcwd
-.segment "INITBSS"
+.segment "INIT"
__cwd: .res __cwd_buf_size
.export __environ, __envcount, __envsize
.import initenv
.constructor env_init
-
+
env_init := initenv
-
-.bss
+
+.data
__environ:
.addr 0
.byte 0
__envsize:
.byte 0
-
-
; Initialization. Will be called from startup!
-.segment "INIT"
+.segment "ONCE"
initheap:
sec
--- /dev/null
+;
+; Christian Groessler, June-2016
+;
+; unsigned char doesclrscr(void);
+;
+; returns 0/1 if after program termination the screen isn't/is cleared
+;
+
+ .export _doesclrscrafterexit
+ .import return0
+
+_doesclrscrafterexit = return0
"Illegal seek", /* ESPIPE */
"Range error", /* ERANGE */
"Bad file number", /* EBADF */
+ "Exec format error", /* ENOEXEC */
"Unknown OS error code", /* EUNKNOWN */
};
; - carry clear and 0 in A for a NMOS 6502 CPU
; - carry set and 1 in A for some CMOS 6502 CPU
; - carry set and 2 in A for a 65816
+; - carry set and 3 in A for a 4510
;
; This function uses a $1A opcode which is a INA on the 816 and ignored
; (interpreted as a NOP) on a NMOS 6502. There are several CMOS versions
_getcpu:
lda #0
- inc a ; .byte $1A
+ inc a ; .byte $1A ; nop on nmos, inc on every cmos
cmp #1
bcc @L9
-; This is at least a 65C02, check for a 65816
+; This is at least a 65C02, check for a 4510
+
+ .byte $42,$ea ; neg on 4510, nop #$ea on 65c02, wdm $ea on 65816
+ cmp #1
+ bne @L8
+
+; check for 65816; after 4510, because $eb there is row (rotate word)
xba ; .byte $eb, put $01 in B accu
dec a ; .byte $3a, A=$00 if 65C02
xba ; .byte $eb, get $01 back if 65816
inc a ; .byte $1a, make $01/$02
+ .byte $2c ; bit instruction to skip next command
+@L8: lda #3 ; CPU_4510 constant
@L9: ldx #0 ; Load high byte of word
rts
+++ /dev/null
-;
-; 2015-10-07, Greg King
-;
-
- .export moveinit
-
- .import __INIT_LOAD__, __INIT_RUN__, __INIT_SIZE__ ; Linker-generated
-
- .macpack cpu
- .macpack generic
-
-
-; Put this in the DATA segment because it is self-modifying code.
-
-.data
-
-; Move the INIT segment from where it was loaded (over the bss segments)
-; into where it must be run (over the BSS segment). The two areas might overlap;
-; and, the segment is moved upwards. Therefore, this code starts at the highest
-; address, and decrements to the lowest address. The low bytes of the starting
-; pointers are not sums. The high bytes are sums; but, they do not include the
-; carry. Both the low-byte sums and the carries will be done when the pointers
-; are indexed by the .Y register.
-
-moveinit:
-
-; First, move the last, partial page.
-; Then, move all of the full pages.
-
- ldy #<__INIT_SIZE__ ; size of partial page
- ldx #>__INIT_SIZE__ + (<__INIT_SIZE__ <> 0) ; number of pages, including partial
-
-L1: dey
-init_load:
- lda __INIT_LOAD__ + (__INIT_SIZE__ & $FF00) - $0100 * (<__INIT_SIZE__ = 0),y
-init_run:
- sta __INIT_RUN__ + (__INIT_SIZE__ & $FF00) - $0100 * (<__INIT_SIZE__ = 0),y
- tya
- bnz L1 ; page not finished
-
- dec init_load+2
- dec init_run+2
- dex
- bnz L1 ; move next page
- rts
lda rand+1
adc #$59
sta rand+1
- pha
lda rand+2
adc #$41
sta rand+2
lda rand+3
adc #$31
sta rand+3
- pla ; return bit 8-22 in (X,A)
- rts
+ rts ; return bit (16-22,24-31) in (X,A)
_srand: sta rand+0 ; Store the seed
stx rand+1
;
.export _cputsxy, _cputs
- .import popa, _gotoxy, _cputc
+ .import gotoxy, _cputc
.importzp ptr1, tmp1
_cputsxy:
sta ptr1 ; Save s for later
stx ptr1+1
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, pop x
+ jsr gotoxy ; Set cursor, pop x and y
jmp L0 ; Same as cputs...
_cputs: sta ptr1 ; Save s
;
.export _chlinexy, _chline
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1
.include "gamate.inc"
_chlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_chline:
.endproc
- .segment "INIT"
+ .segment "ONCE"
initclock:
lda #0
ldx #3
.macpack longbranch
- .segment "INIT"
+ .segment "ONCE"
initconio:
lda #0
sta LCD_XPOS
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.import PLOT
.import xsize
.import fontdata
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
ldx #0
stx ZP_IRQ_CTRL ; disable calling cartridge IRQ/NMI handler
- ; Setup stack and memory mapping
+ ; Set up stack and memory mapping
;ldx #$FF ; Stack top ($01FF)
dex
txs
; Copy the .data segment to RAM
jsr copydata
- ; setup the stack
+ ; Set up the stack
lda #<(__RAM_START__+__RAM_SIZE__)
+ ldx #>(__RAM_START__+__RAM_SIZE__)
sta sp
- lda #>(__RAM_START__+__RAM_SIZE__)
- sta sp + 1
+ stx sp + 1
; Call module constructors
jsr initlib
lda #1
sta ZP_IRQ_CTRL ; enable calling cartridge IRQ/NMI handler
- cli ; allow IRQ only after constructors have run
+ cli ; allow IRQ only after constructors have run
; Pass an empty command line
jsr push0 ; argc
;
.export _cvlinexy, _cvline
- .import popa, _gotoxy, putchar, newline
+ .import gotoxy, putchar, newline
.importzp tmp1
.include "gamate.inc"
_cvlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline
_cvline:
; void gotoxy (unsigned char x, unsigned char y);
;
- .export _gotoxy
+ .export gotoxy, _gotoxy
.import popa, plot
.include "gamate.inc"
.include "extzp.inc"
+gotoxy:
+ jsr popa ; Get X
+
_gotoxy:
sta CURS_Y ; Set Y
jsr popa ; Get X
.include "extzp.inc"
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
; a constructor
;
;
.export NMIStub
- .segment "INIT"
+ .segment "ONCE"
NMIStub:
; A is saved by the BIOS
../lib/apple2enh.lib:
@$(MAKE) --no-print-directory apple2enh
-../targetutil/convert.system: ../libwrk/$(TARGET)/convert.o ../lib/apple2enh.lib | ../targetutil
+../target/$(TARGET)/util/convert.system: ../libwrk/$(TARGET)/convert.o ../lib/apple2enh.lib | ../target/$(TARGET)/util
$(LD65) -o $@ -C apple2enh-system.cfg $^
-$(TARGET): ../targetutil/convert.system
+$(TARGET): ../target/$(TARGET)/util/convert.system
.include "geossym.inc"
-.segment "INIT"
+.segment "ONCE"
initscrsize:
.ifdef __GEOS_CBM__
ldy ysize
rts
-.bss
+.segment "INIT"
xsize:
.res 1
; void cclear (unsigned char length);
.export _cclearxy, _cclear
- .import popa, _gotoxy, fixcursor
+ .import gotoxy, fixcursor
.importzp cursor_x, cursor_y, cursor_c
.include "jumptab.inc"
_cclearxy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_cclear:
; void chline (unsigned char length);
.export _chlinexy, _chline
- .import popa, _gotoxy, fixcursor
+ .import gotoxy, fixcursor
.importzp cursor_x, cursor_y, cursor_c
.include "jumptab.inc"
_chlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_chline:
; UPLINE = ?, KEY_UPARROW = GOTOY, ...
.export _cputcxy, _cputc
- .import _gotoxy, fixcursor
- .import popa
+ .import gotoxy, fixcursor
.import xsize,ysize
.importzp cursor_x, cursor_y, cursor_c, cursor_r
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
; void cvline (unsigned char length);
.export _cvlinexy, _cvline
- .import popa, _gotoxy, fixcursor
+ .import gotoxy, fixcursor
.importzp cursor_x, cursor_y, cursor_r
.include "jumptab.inc"
_cvlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_cvline:
; void gotoy (unsigned char y);
; void gotoxy (unsigned char x, unsigned char y);
- .export _gotox, _gotoy, _gotoxy, fixcursor
+ .export _gotox, _gotoy, gotoxy, _gotoxy, fixcursor
.import popa
.importzp cursor_x, cursor_y, cursor_c, cursor_r
sta cursor_r
jmp fixcursor
+gotoxy:
+ jsr popa
+
_gotoxy:
sta cursor_r
jsr popa
; Setup arguments for main
;
; There is always either 1 or 3 arguments:
-; <program name>,0
+; <program name>, 0
; or
; <program name>, <data file name>, <data disk name>, 0
; the 2nd case is when using DeskTop user drags an icon of a file and drops it
.include "const.inc"
.include "geossym.inc"
-.segment "INIT"
+.segment "ONCE"
; Setup arguments for main
.word dataDiskName ; dataDiskName
.word $0000 ; last one must be NULL
-.bss
+.segment "INIT"
argv0:
.res 17 ; Program name
; This header is required for BLL builds.
;
.import __BSS_LOAD__
- .import __RAM_START__
+ .import __MAIN_START__
.export __BLLHDR__: absolute = 1
; ------------------------------------------------------------------------
.segment "BLLHDR"
.word $0880
- .dbyt __RAM_START__
- .dbyt __BSS_LOAD__ - __RAM_START__ + 10
+ .dbyt __MAIN_START__
+ .dbyt __BSS_LOAD__ - __MAIN_START__ + 10
.byte $42,$53
.byte $39,$33
-
;
.include "lynx.inc"
.include "extzp.inc"
- .import __BLOCKSIZE__
+ .import __BANK0BLOCKSIZE__
.export __BOOTLDR__: absolute = 1
lda __iodat
sta IODAT
stz _FileBlockByte
- lda #<($100-(>__BLOCKSIZE__))
+ lda #<($100-(>__BANK0BLOCKSIZE__))
sta _FileBlockByte+1
ply
plx
;-----------------------------------------------------------------------------
; Enable the interrupt that update_clock needs.
;
- .segment "INIT"
+ .segment "ONCE"
init_clock:
lda #%10000000
tsb VTIMCTLA
.import zerobss
.import callmain
.import _main
- .import __RAM_START__, __RAM_SIZE__, __STACKSIZE__
+ .import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__
.include "zeropage.inc"
.include "extzp.inc"
; Set up the stack.
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
- lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp+1
+ stx sp+1
; Init Mickey.
;
.include "lynx.inc"
.import __STARTOFDIRECTORY__
- .import __RAM_START__
- .import __CODE_SIZE__,__DATA_SIZE__,__RODATA_SIZE__
- .import __STARTUP_SIZE__,__INIT_SIZE__,__LOWCODE_SIZE__
- .import __BLOCKSIZE__
+ .import __MAIN_START__
+ .import __CODE_SIZE__, __DATA_SIZE__, __RODATA_SIZE__
+ .import __STARTUP_SIZE__, __ONCE_SIZE__, __LOWCODE_SIZE__
+ .import __BANK0BLOCKSIZE__
.export __DEFDIR__: absolute = 1
.segment "DIRECTORY"
__DIRECTORY_START__:
-off0=__STARTOFDIRECTORY__+(__DIRECTORY_END__-__DIRECTORY_START__)
-blocka=off0/__BLOCKSIZE__
+off0 = __STARTOFDIRECTORY__ + (__DIRECTORY_END__ - __DIRECTORY_START__)
+blocka = off0 / __BANK0BLOCKSIZE__
; Entry 0 - first executable
-block0=off0/__BLOCKSIZE__
-len0=__STARTUP_SIZE__+__INIT_SIZE__+__CODE_SIZE__+__DATA_SIZE__+__RODATA_SIZE__+__LOWCODE_SIZE__
+block0 = off0 / __BANK0BLOCKSIZE__
+len0 = __STARTUP_SIZE__ + __ONCE_SIZE__ + __CODE_SIZE__ + __DATA_SIZE__ + __RODATA_SIZE__ + __LOWCODE_SIZE__
.byte <block0
- .word off0 & (__BLOCKSIZE__ - 1)
+ .word off0 & (__BANK0BLOCKSIZE__ - 1)
.byte $88
- .word __RAM_START__
+ .word __MAIN_START__
.word len0
__DIRECTORY_END__:
-
;
; This header contains data for emulators like Handy and Mednafen
;
- .import __BLOCKSIZE__
+ .import __BANK0BLOCKSIZE__
+ .import __BANK1BLOCKSIZE__
.export __EXEHDR__: absolute = 1
; EXE header
.segment "EXEHDR"
.byte 'L','Y','N','X' ; magic
- .word __BLOCKSIZE__ ; bank 0 page size
- .word __BLOCKSIZE__ ; bank 1 page size
+ .word __BANK0BLOCKSIZE__ ; bank 0 page size
+ .word __BANK1BLOCKSIZE__ ; bank 1 page size
.word 1 ; version number
.asciiz "Cart name " ; 32 bytes cart name
.asciiz "Manufacturer " ; 16 bytes manufacturer
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda #<IRQStub
;---------------------------------------------------------------------------
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
-.segment "INIT"
+.segment "ONCE"
.proc initmainargs
-../tgi/nes-64-56-2.tgi: ../libwrk/nes/clrscr.o \
- ../libwrk/nes/cputc.o \
- ../libwrk/nes/get_tv.o \
- ../libwrk/nes/gotoxy.o \
- ../libwrk/nes/popa.o \
- ../libwrk/nes/ppu.o \
- ../libwrk/nes/ppubuf.o \
- ../libwrk/nes/setcursor.o
+../target/nes/drv/tgi/nes-64-56-2.tgi: \
+ ../libwrk/nes/clrscr.o \
+ ../libwrk/nes/cputc.o \
+ ../libwrk/nes/get_tv.o \
+ ../libwrk/nes/gotoxy.o \
+ ../libwrk/nes/popa.o \
+ ../libwrk/nes/ppu.o \
+ ../libwrk/nes/ppubuf.o \
+ ../libwrk/nes/setcursor.o
;
.export _cclearxy, _cclear
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1
_cclearxy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cclear
_cclear:
;
.export _chlinexy, _chline
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1
.include "nes.inc"
_chlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_chline:
.export _cputcxy, _cputc, cputdirect, putchar
.export newline
.constructor initconio
- .import popa, _gotoxy
+ .import gotoxy
.import ppuinit, paletteinit, ppubuf_put
.import setcursor
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
jmp ppubuf_put
;-----------------------------------------------------------------------------
-; Initialize the conio subsystem. Code goes into the INIT segment, which may
+; Initialize the conio subsystem. Code goes into the ONCE segment, which may
; be reused after startup.
-.segment "INIT"
+.segment "ONCE"
initconio:
jsr ppuinit
; Set up the stack.
lda #<(__SRAM_START__ + __SRAM_SIZE__)
+ ldx #>(__SRAM_START__ + __SRAM_SIZE__)
sta sp
- lda #>(__SRAM_START__ + __SRAM_SIZE__)
- sta sp+1 ; Set argument stack ptr
+ stx sp+1 ; Set argument stack ptr
; Call the module constructors.
; Interrupt exit
-irq2:
-irq1:
-timerirq:
irq:
rti
.segment "VECTORS"
- .word irq2 ; $fff4 ?
- .word irq1 ; $fff6 ?
- .word timerirq ; $fff8 ?
.word nmi ; $fffa vblank nmi
.word start ; $fffc reset
.word irq ; $fffe irq / brk
;
.export _cvlinexy, _cvline
- .import popa, _gotoxy, putchar, newline
+ .import gotoxy, putchar, newline
.importzp tmp1
.include "nes.inc"
_cvlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline
_cvline:
; void gotoxy (unsigned char x, unsigned char y);
;
- .export _gotoxy
+ .export gotoxy, _gotoxy
.import setcursor
.import popa
.include "nes.inc"
-.proc _gotoxy
+gotoxy:
+ jsr popa ; Get Y
+_gotoxy:
sta CURS_Y ; Set Y
jsr popa ; Get X
sta CURS_X ; Set X
tay
ldx CURS_Y
jmp setcursor ; Set the cursor position
-
-.endproc
-
-
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
rts
;---------------------------------------------------------------------------
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
-.segment "INIT"
+.segment "ONCE"
.proc initmainargs
;-----------------------------------------------------------------------------
+.segment "ONCE"
+
.proc ppuinit
lda #%10101000
.endproc
-
;-----------------------------------------------------------------------------
.proc paletteinit
bne @loop
rts
-
+
.endproc
;-----------------------------------------------------------------------------
; add "-u __BOOT__" to the cl65/ld65 command line. Then, the linker
; will import this symbol name; and, link this module at the front
; of your program file.
-;
- .export __BOOT__:abs = 1
- .import __RAM_START__, __RAM_SIZE__, __BSS_RUN__
+ .export __BOOT__ : abs = 1
+
+ .import __MAIN_START__, __MAIN_SIZE__, __BSS_RUN__
; ------------------------------------------------------------------------
-load_addr := __RAM_START__
-load_size = __BSS_RUN__ - __RAM_START__
-ram_top := __RAM_START__ + __RAM_SIZE__
+load_addr := __MAIN_START__
+load_size = __BSS_RUN__ - __MAIN_START__
+ram_top := __MAIN_START__ + __MAIN_SIZE__
.segment "BOOT"
;
.export _cclearxy, _cclear
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1
_cclearxy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cclear
_cclear:
.include "zeropage.inc"\r
\r
; Initialize one-character buffer that is filled by kbhit()\r
- .segment "INIT"\r
+ .segment "ONCE"\r
initcgetc:\r
lda #$00\r
sta CHARBUF ; No character in buffer initially\r
;
.export _chlinexy, _chline
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1
_chlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_chline:
.import _main
.export __STARTUP__ : absolute = 1 ; Mark as startup
-.import __RAM_START__, __RAM_SIZE__ ; Linker generated
+.import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__
.import zerobss, initlib, donelib
; ---------------------------------------------------------------------------
; Set cc65 argument stack pointer
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
- lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp+1
+ stx sp+1
; ---------------------------------------------------------------------------
; Initialize memory storage
;
.export _cvlinexy, _cvline
- .import popa, _gotoxy, putchar, newline
+ .import gotoxy, putchar, newline
.importzp tmp1
_cvlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline
_cvline:
;
; void gotoxy (unsigned char x, unsigned char y);
;
- .export _gotoxy
+ .export gotoxy, _gotoxy
.import popa, plot
.include "extzp.inc"
+gotoxy:
+ jsr popa ; Get Y
+
_gotoxy:
sta CURS_Y ; Set Y
jsr popa ; Get X
\r
_cputcxy:\r
pha ; Save C\r
- jsr popa ; Get Y\r
- jsr _gotoxy ; Set cursor, drop x\r
+ jsr gotoxy ; Set cursor, drop x and y\r
pla ; Restore C\r
\r
; Plot a character - also used as internal function\r
.macro osi_screen_funcs ScrBase, ScrRamSize, ScrFirstChar, \\r
ScrWidth, ScrHeight, ScrollDist\r
\r
- .import popa, _gotoxy\r
+ .import gotoxy\r
.import _memmove, _memset, pushax\r
.importzp ptr1\r
\r
;
.export _chlinexy, _chline
- .import popa, _gotoxy, cputdirect
+ .import gotoxy, cputdirect
.importzp tmp1
.include "pce.inc"
_chlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length
_chline:
.endproc
- .segment "INIT"
+ .segment "ONCE"
initclock:
lda #0
ldx #3
.macpack longbranch
- .segment "INIT"
+ .segment "ONCE"
initconio:
jsr vce_init
jsr psg_init
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.import PLOT
.import xsize
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
start:
- ; setup the CPU and System-IRQ
+ ; Set up the CPU and System-IRQ
; Initialize CPU
-
sei
nop
- csh ; set high speed CPU mode
+ csh ; Set high speed CPU mode
nop
cld
nop
- ; Setup stack and memory mapping
+ ; Set up stack and memory mapping
ldx #$FF ; Stack top ($21FF)
txs
- ; at startup all MPRs are set to 0, so init them
+ ; At startup all MPRs are set to 0, so init them
lda #$ff
tam #%00000001 ; 0000-1FFF = Hardware page
lda #$F8
; Copy the .data segment to RAM
tii __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__
- ; setup the stack
+ ; Set up the stack
lda #<(__RAM_START__+__RAM_SIZE__)
+ ldx #>(__RAM_START__+__RAM_SIZE__)
sta sp
- lda #>(__RAM_START__+__RAM_SIZE__)
- sta sp + 1
+ stx sp + 1
; Call module constructors
jsr initlib
jsr push0 ; argv
ldy #4 ; Argument size
- jsr _main ; call the users code
+ jsr _main ; Call the users code
; Call module destructors. This is also the _exit entry.
_exit:
;
.export _cvlinexy, _cvline
- .import popa, _gotoxy, putchar, newline
+ .import gotoxy, putchar, newline
.importzp tmp1
.include "pce.inc"
_cvlinexy:
pha ; Save the length
- jsr popa ; Get y
- jsr _gotoxy ; Call this one, will pop params
+ jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _cvline
_cvline:
; void gotoxy (unsigned char x, unsigned char y);
;
- .export _gotoxy
+ .export gotoxy, _gotoxy
.import popa, plot
.include "pce.inc"
.include "extzp.inc"
+gotoxy:
+ jsr popa ; Get Y
+
_gotoxy:
sta CURS_Y ; Set Y
jsr popa ; Get X
.include "extzp.inc"
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
; a constructor
;
.export psg_init
- .segment "INIT"
+ .segment "ONCE"
psg_init:
clx
stz PSG_GLOBAL_PAN ; Clear global balance
.export vce_init
- .segment "INIT"
+ .segment "ONCE"
vce_init:
; Set CTA to zero
stz VCE_ADDR_LO
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.include "pet.inc"
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
; ------------------------------------------------------------------------
-.segment "INITBSS"
+.segment "INIT"
zpsave: .res zpspace
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda IRQVec
;---------------------------------------------------------------------------
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
-.segment "INIT"
+.segment "ONCE"
.proc initmainargs
.endproc
-.segment "INITBSS"
+.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
.constructor initkbd
.destructor donekbd
-.segment "INIT" ; Special init code segment may get overwritten
+.segment "ONCE" ; Special init code segment may get overwritten
.proc initkbd
.endproc
+fnkeys: .byte $01, $01, $01, $01, $01, $01, $01, $01
+ .byte 133, 137, 134, 138, 135, 139, 136, 140
+
.segment "LOWCODE" ; Accesses the ROM - must go into low mem
rts
.endproc
-
-
-; Function key table, readonly
-
-.rodata
-fnkeys: .byte $01, $01, $01, $01, $01, $01, $01, $01
- .byte 133, 137, 134, 138, 135, 139, 136, 140
-
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.import PLOT
.include "plus4.inc"
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
.import callirq_y, initlib, donelib
.import callmain, zerobss
.import __INTERRUPTOR_COUNT__
- .import __RAM_START__, __RAM_SIZE__ ; Linker generated
+ .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; Linker generated
.importzp ST
; of the usable RAM.
tsx
- stx spsave ; save system stk ptr
+ stx spsave ; Save system stk ptr
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
- lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp+1
+ stx sp+1
; Set up the IRQ vector in the banked RAM; and, switch off the ROM.
irqcount: .byte 0
-.segment "INITBSS"
+.segment "INIT"
zpsave: .res zpspace
;
-; Standard joystick driver for the Plus/4. May be used multiple times when linked
-; to the statically application.
+; Standard joystick driver for the Plus/4 and C16.
+; May be used multiple times when linked statically to an application.
;
-; Ullrich von Bassewitz, 2002-12-21
+; 2002-12-21, Ullrich von Bassewitz
+; 2016-06-18, Greg King
;
- .include "zeropage.inc"
-
.include "joy-kernel.inc"
.include "joy-error.inc"
.include "plus4.inc"
- .macpack generic
.macpack module
; Driver signature
- .byte $6A, $6F, $79 ; "joy"
+ .byte $6A, $6F, $79 ; ASCII "joy"
.byte JOY_API_VERSION ; Driver API version number
; Library reference
.byte $02 ; JOY_DOWN
.byte $04 ; JOY_LEFT
.byte $08 ; JOY_RIGHT
- .byte $10 ; JOY_FIRE
+ .byte $80 ; JOY_FIRE
.byte $00 ; JOY_FIRE2 unavailable
.byte $00 ; Future expansion
.byte $00 ; Future expansion
; READ: Read a particular joystick passed in A.
;
-READ: ldy #$FA ; Load index for joystick #1
+READ: ldy #%11111011 ; Load index for joystick #1
tax ; Test joystick number
beq @L1
- ldy #$FB ; Load index for joystick #2
+ ldy #%11111101 ; Load index for joystick #2
+ ldx #>$0000 ; (Return unsigned int)
@L1: sei
- sty TED_KBD
- lda TED_KBD
+ sty TED_KBD ; Read a joystick ...
+ lda TED_KBD ; ... and some keys -- it's unavoidable
cli
- ldx #$00 ; Clear high byte
- and #$1F
- eor #$1F
- rts
+ eor #%11111111
+; The fire buttons are in bits 6 and 7. Both of them cannot be %1 together.
+; Therefore, bit 6 can be merged with bit 7.
+
+ clc
+ adc #%01000000
+ rts
--- /dev/null
+;
+; 2002-11-22, Ullrich von Bassewitz
+; 2016-08-07, Greg King
+;
+; SCNKEY replacement function
+;
+
+ .export SCNKEY
+
+ .include "plus4.inc"
+
+.segment "LOWCODE" ; Must go into low memory
+
+.proc SCNKEY
+ sta ENABLE_ROM ; Enable the ROM
+ jsr $FF9F ; Call the ROM routine
+ sta ENABLE_RAM ; Switch back to RAM
+ rts ; Return to caller
+.endproc
--- /dev/null
+;
+; 2002-11-22, Ullrich von Bassewitz
+; 2016-08-07, Greg King
+;
+; UDTIM replacement function
+;
+
+ .export UDTIM
+
+ .include "plus4.inc"
+
+.segment "LOWCODE" ; Must go into low memory
+
+.proc UDTIM
+ sta ENABLE_ROM ; Enable the ROM
+ jsr $FFEA ; Call the ROM routine
+ sta ENABLE_RAM ; Switch back to RAM
+ rts ; Return to caller
+.endproc
REM = $8f ; BASIC token-code
NAME_LEN = 16 ; Maximum length of command-name
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
-.segment "INIT"
+.segment "ONCE"
initmainargs:
stx __argv + 1
rts
-.segment "INITBSS"
+.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
; --------------------------------------------------------------------------
; Initialize library modules
-.segment "INIT"
+.segment "ONCE"
.proc initlib
; Initialization code. This is a constructor, so it is called on startup if
; the linker has detected references to this module.
-.segment "INIT"
+.segment "ONCE"
.proc initstkchk
; ----------------------------------------------------------------------------
; Data
-.segment "INITBSS"
+.segment "INIT"
; Initial stack pointer value. Stack is reset to this in case of overflows to
; allow program exit processing.
.import zerobss, callmain
.import initlib, donelib
.import exit
- .import __RAM_START__, __RAM_SIZE__ ; Linker generated
+ .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; Linker generated
.include "zeropage.inc"
cld
ldx #$FF
txs
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- ldx #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
stx sp+1
jsr zerobss
.constructor initmainargs, 24
.import __argc, __argv, args
- .segment "INIT"
+ .segment "ONCE"
initmainargs:
lda #<__argv
; Initialize data.
jsr copydata
- lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp+1 ; Set argument stack ptr
- stz sp ; #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ ldx #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ sta sp
+ stx sp+1 ; Set argument stack ptr
jsr initlib
jsr _main
_exit: jsr donelib
.export _cputcxy, _cputc, cputdirect, putchar
.export newline, plot
- .import popa, _gotoxy
+ .import gotoxy
.import PLOT
.include "vic20.inc"
_cputcxy:
pha ; Save C
- jsr popa ; Get Y
- jsr _gotoxy ; Set cursor, drop x
+ jsr gotoxy ; Set cursor, drop x and y
pla ; Restore C
; Plot a character - also used as internal function
.import zerobss, push0
.import callmain
.import RESTOR, BSOUT, CLRCH
- .import __RAM_START__, __RAM_SIZE__ ; Linker generated
+ .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; Linker generated
.importzp ST
tsx
stx spsave ; Save the system stack ptr
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
- lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- sta sp+1 ; Set argument stack ptr
+ stx sp+1 ; Set argument stack ptr
; Call the module constructors.
; ------------------------------------------------------------------------
-.segment "INITBSS"
+.segment "INIT"
zpsave: .res zpspace
; ------------------------------------------------------------------------
-.segment "INIT"
+.segment "ONCE"
initirq:
lda IRQVec
;-----------------------------------------------------------------------------
; All functions are available in the kernal jump table
-CINT = $FF81
-IOINIT = $FF84
-RAMTAS = $FF87
+CINT = $E518 ; No entries are in the kernal jump table of the Vic20 for these three (3) functions.
+IOINIT = $FDF9 ; The entries for these functions have been set to point directly to the functions
+RAMTAS = $FD8D ; in the kernal to maintain compatibility with the other Commodore platforms.
RESTOR = $FF8A
VECTOR = $FF8D
SETMSG = $FF90
REM = $8f ; BASIC token-code
NAME_LEN = 16 ; Maximum length of command-name
-; Get possible command-line arguments. Goes into the special INIT segment,
+; Get possible command-line arguments. Goes into the special ONCE segment,
; which may be reused after the startup code is run
-.segment "INIT"
+.segment "ONCE"
initmainargs:
stx __argv + 1
rts
-.segment "INITBSS"
+.segment "INIT"
term: .res 1
name: .res NAME_LEN + 1
;
-; Piotr Fusik, 21.09.2003
+; 2003-09-21, Piotr Fusik
+; 2016-07-19, Greg King
;
; unsigned __fastcall__ inflatemem (char* dest, const char* source);
;
.import incsp2
.importzp sp, sreg, ptr1, ptr2, ptr3, ptr4, tmp1
+ .macpack cpu
+
; --------------------------------------------------------------------------
;
; Constants
;
; Pointer to the compressed data.
-inputPointer = ptr1 ; 2 bytes
+inputPointer := ptr1 ; 2 bytes
; Pointer to the uncompressed data.
-outputPointer = ptr2 ; 2 bytes
+outputPointer := ptr2 ; 2 bytes
; Local variables.
; As far as there is no conflict, same memory locations are used
; for different variables.
-inflateDynamicBlock_cnt = ptr3 ; 1 byte
-inflateCodes_src = ptr3 ; 2 bytes
-buildHuffmanTree_src = ptr3 ; 2 bytes
-getNextLength_last = ptr3 ; 1 byte
-getNextLength_index = ptr3+1 ; 1 byte
+inflateDynamicBlock_cnt := ptr3 ; 1 byte
+inflateCodes_src := ptr3 ; 2 bytes
+buildHuffmanTree_src := ptr3 ; 2 bytes
+getNextLength_last := ptr3 ; 1 byte
+getNextLength_index := ptr3+1 ; 1 byte
-buildHuffmanTree_ptr = ptr4 ; 2 bytes
-fetchCode_ptr = ptr4 ; 2 bytes
-getBits_tmp = ptr4 ; 1 byte
+buildHuffmanTree_ptr := ptr4 ; 2 bytes
+fetchCode_ptr := ptr4 ; 2 bytes
+getBits_tmp := ptr4 ; 1 byte
-moveBlock_len = sreg ; 2 bytes
-inflateDynamicBlock_np = sreg ; 1 byte
-inflateDynamicBlock_nd = sreg+1 ; 1 byte
+moveBlock_len := sreg ; 2 bytes
+inflateDynamicBlock_np := sreg ; 1 byte
+inflateDynamicBlock_nd := sreg+1 ; 1 byte
-getBit_hold = tmp1 ; 1 byte
+getBit_hold := tmp1 ; 1 byte
; --------------------------------------------------------------------------
sta inputPointer
stx inputPointer+1
; outputPointer = dest
-.ifpc02
+.if (.cpu & CPU_ISET_65SC02)
lda (sp)
ldy #1
.else
; return outputPointer - dest;
lda outputPointer
-.ifpc02
+.if (.cpu & CPU_ISET_65SC02)
sbc (sp) ; C flag is set
ldy #1
.else
ldy #1
sty getBit_hold
; Get 16-bit length
- ldx #inputPointer
- lda (0,x)
+ ldx #0
+ lda (inputPointer,x)
sta moveBlock_len
lda (inputPointer),y
sta moveBlock_len+1
moveBlock:
ldy moveBlock_len
beq moveBlock_1
-.ifpc02
+.if (.cpu & CPU_ISET_65SC02)
.else
ldy #0
.endif
inc moveBlock_len+1
moveBlock_1:
- lda (0,x)
-.ifpc02
+ lda (inputPointer,x)
+.if (.cpu & CPU_ISET_65SC02)
sta (outputPointer)
.else
sta (outputPointer),y
.endif
- inc 0,x
+ inc inputPointer
bne moveBlock_2
- inc 1,x
+ inc inputPointer+1
moveBlock_2:
inc outputPointer
bne moveBlock_3
inc outputPointer+1
moveBlock_3:
-.ifpc02
+.if (.cpu & CPU_ISET_65SC02)
dey
.else
dec moveBlock_len
jsr fetchPrimaryCode
bcs inflateCodes_2
; Literal code
-.ifpc02
+.if (.cpu & CPU_ISET_65SC02)
sta (outputPointer)
.else
ldy #0
getBits:
cpx #0
beq getBits_ret
-.ifpc02
+.if (.cpu & CPU_ISET_65SC02)
stz getBits_tmp
dec getBits_tmp
.else
lsr getBit_hold
bne getBit_ret
pha
-.ifpc02
+.if (.cpu & CPU_ISET_65SC02)
lda (inputPointer)
.else
sty getBit_hold
bne getBit_1
inc inputPointer+1
getBit_1:
- ror a ; C flag is set
+ ror a ; (C flag was set)
sta getBit_hold
pla
getBit_ret:
; Sorted codes.
sortedCodes:
.res 256+1+29+30+2
-
-
-
# This Makefile requires GNU make
#
-# Enter the target system here
-SYS = c64
-
-# Determine the path to the executables and libraries. If the samples
-# directory is part of a complete source tree, use the stuff from that
-# source tree; otherwise, use the "install" directories.
-ifeq "$(wildcard ../src)" ""
-# No source tree
-MOUS = /usr/lib/cc65/mou/$(SYS)*.mou
-TGI = /usr/lib/cc65/tgi/$(SYS)*.tgi
-ifneq "$(wildcard /usr/local/lib/cc65)" ""
-MOUS = /usr/local/lib/cc65/mou/$(SYS)*.mou
-TGI = /usr/local/lib/cc65/tgi/$(SYS)*.tgi
+# Run 'make SYS=<target>' or set a SYS env
+# var to build for another target system.
+SYS ?= c64
+
+ifneq ($(shell echo),)
+ CMD_EXE = 1
endif
-ifdef CC65_HOME
-MOUS = $(CC65_HOME)/mou/$(SYS)*.mou
-TGI = $(CC65_HOME)/tgi/$(SYS)*.tgi
+
+ifdef CMD_EXE
+ NULLDEV = nul:
+ DEL = -del /f
+ RMDIR = rmdir /s /q
+else
+ NULLDEV = /dev/null
+ DEL = $(RM)
+ RMDIR = $(RM) -r
endif
-CLIB = --lib $(SYS).lib
-CL = cl65
-CC = cc65
-AS = ca65
-LD = ld65
+ifdef CC65_HOME
+ AS = $(CC65_HOME)/bin/ca65
+ CC = $(CC65_HOME)/bin/cc65
+ CL = $(CC65_HOME)/bin/cl65
+ LD = $(CC65_HOME)/bin/ld65
else
-# "samples/" is a part of a complete source tree.
-export CC65_HOME := $(abspath ..)
-MOUS = ../mou/$(SYS)*.mou
-TGI = ../tgi/$(SYS)*.tgi
-CLIB = ../lib/$(SYS).lib
-CL = ../bin/cl65
-CC = ../bin/cc65
-AS = ../bin/ca65
-LD = ../bin/ld65
+ AS := $(if $(wildcard ../bin/ca65*),../bin/ca65,ca65)
+ CC := $(if $(wildcard ../bin/cc65*),../bin/cc65,cc65)
+ CL := $(if $(wildcard ../bin/cl65*),../bin/cl65,cl65)
+ LD := $(if $(wildcard ../bin/ld65*),../bin/ld65,ld65)
endif
-# This one comes with VICE
-C1541 = c1541
+ifneq ($(filter disk samples.%,$(MAKECMDGOALS)),)
+ TARGET_PATH := $(shell $(CL) --print-target-path)
+
+ EMD := $(wildcard $(TARGET_PATH)/$(SYS)/drv/emd/*)
+ MOU := $(wildcard $(TARGET_PATH)/$(SYS)/drv/mou/*)
+ TGI := $(wildcard $(TARGET_PATH)/$(SYS)/drv/tgi/*)
+
+ # This one comes with VICE
+ C1541 ?= c1541
+
+ # For this one see http://applecommander.sourceforge.net/
+ AC ?= ac.jar
+
+ # For this one see http://www.horus.com/~hias/atari/
+ DIR2ATR ?= dir2atr
+
+ DISK_c64 = samples.d64
+ DISK_apple2 = samples.dsk
+ DISK_apple2enh = samples.dsk
+ DISK_atari = samples.atr
+ DISK_atarixl = samples.atr
+endif
# --------------------------------------------------------------------------
# System-dependent settings
# The Apple machines need the start address adjusted when using TGI
-LDFLAGS_mandelbrot_apple2 = --start-addr 0x4000
-LDFLAGS_tgidemo_apple2 = --start-addr 0x4000
+LDFLAGS_mandelbrot_apple2 = --start-addr 0x4000
LDFLAGS_mandelbrot_apple2enh = --start-addr 0x4000
-LDFLAGS_tgidemo_apple2enh = --start-addr 0x4000
+LDFLAGS_tgidemo_apple2 = --start-addr 0x4000
+LDFLAGS_tgidemo_apple2enh = --start-addr 0x4000
# The Apple ][ needs the start address adjusted for the mousetest
LDFLAGS_mousetest_apple2 = --start-addr 0x4000
-# The atarixl target needs the start address adjusted when using TGI
-LDFLAGS_mandelbrot_atarixl = --start-addr 0x4000
-LDFLAGS_tgidemo_atarixl = --start-addr 0x4000
+# The Apple machines need the end address adjusted for large programs
+LDFLAGS_gunzip65_apple2 = -D __HIMEM__=0xBF00
+LDFLAGS_gunzip65_apple2enh = -D __HIMEM__=0xBF00
# The atari target needs to reserve some memory when using TGI
LDFLAGS_mandelbrot_atari = -D __RESERVED_MEMORY__=0x2000
-LDFLAGS_tgidemo_atari = -D __RESERVED_MEMORY__=0x2000
+LDFLAGS_tgidemo_atari = -D __RESERVED_MEMORY__=0x2000
+
+# The atarixl target needs the start address adjusted when using TGI
+LDFLAGS_mandelbrot_atarixl = --start-addr 0x4000
+LDFLAGS_tgidemo_atarixl = --start-addr 0x4000
# --------------------------------------------------------------------------
# Generic rules
+.PHONY: all mostlyclean clean install zip samples disk
+
%: %.c
%: %.s
.c.o:
- @echo $<
- @$(CC) $(CFLAGS) -Oirs --codesize 500 -T -g -t $(SYS) $<
- @$(AS) $(<:.c=.s)
+ $(CC) $(CFLAGS) -Oirs --codesize 500 -T -g -t $(SYS) $<
+ $(AS) $(<:.c=.s)
.s.o:
- @echo $<
- @$(AS) $(AFLAGS) -t $(SYS) $<
+ $(AS) $(AFLAGS) -t $(SYS) $<
.PRECIOUS: %.o
.o:
- @$(LD) $(LDFLAGS_$(@F)_$(SYS)) -o $@ -t $(SYS) -m $@.map $^ $(CLIB)
+ $(LD) $(LDFLAGS_$(@F)_$(SYS)) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib
# --------------------------------------------------------------------------
-# List of executables. This list could be made target-dependent by checking
-# $(SYS).
-
-EXELIST = ascii \
- diodemo \
- enumdevdir \
- fire \
- gunzip65 \
- hello \
- mandelbrot \
- mousetest \
- multdemo \
- nachtm \
- ovrldemo \
- plasma \
- sieve \
- tgidemo
+# List of executables
+
+EXELIST_c64 = \
+ ascii \
+ enumdevdir \
+ fire \
+ gunzip65 \
+ hello \
+ mandelbrot \
+ mousetest \
+ multdemo \
+ nachtm \
+ ovrldemo \
+ plasma \
+ sieve \
+ tgidemo
+
+EXELIST_apple2 = \
+ ascii \
+ diodemo \
+ enumdevdir \
+ gunzip65 \
+ hello \
+ mandelbrot \
+ mousetest \
+ multdemo \
+ ovrldemo \
+ sieve \
+ tgidemo
+
+EXELIST_apple2enh = $(EXELIST_apple2)
+
+EXELIST_atari = \
+ ascii \
+ gunzip65 \
+ hello \
+ mandelbrot \
+ mousetest \
+ multdemo \
+ ovrldemo \
+ sieve \
+ tgidemo
+
+EXELIST_atarixl = $(EXELIST_atari)
+
+EXELIST_atari2600 = \
+ atari2600hello
# --------------------------------------------------------------------------
-# Rules to make the binaries
+# Rules to make the binaries and the disk
+
+samples: $(EXELIST_$(SYS))
+
+disk: $(DISK_$(SYS))
-.PHONY: all
-all: $(EXELIST)
+all:
# --------------------------------------------------------------------------
# Overlay rules. Overlays need special ld65 configuration files. Also, the
# overlay file-names are shortenned to fit the Atari's 8.3-character limit.
-multdemo: multidemo.o
- @$(LD) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(CLIB)
+multdemo: multidemo.o
+ $(LD) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(SYS).lib
-ovrldemo: overlaydemo.o
- @$(LD) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(CLIB)
+ovrldemo: overlaydemo.o
+ $(LD) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(SYS).lib
+
+OVERLAYLIST := $(foreach I,1 2 3,multdemo.$I ovrldemo.$I)
# --------------------------------------------------------------------------
# Rule to make a CBM disk with all samples. Needs the c1541 program that comes
# with the VICE emulator.
-.PHONY: disk
-disk: samples.d64
+define D64_WRITE_recipe
+
+$(C1541) -attach $@ -write $(file) $(notdir $(file)) >$(NULLDEV)
+
+endef # D64_WRITE_recipe
+
+samples.d64: samples
+ @$(C1541) -format samples,AA d64 $@ >$(NULLDEV)
+ $(foreach file,$(EXELIST_$(SYS)),$(D64_WRITE_recipe))
+ $(foreach file,$(OVERLAYLIST),$(D64_WRITE_recipe))
+ $(foreach file,$(EMD) $(MOU) $(TGI),$(D64_WRITE_recipe))
+
+# --------------------------------------------------------------------------
+# Rule to make an Apple II disk with all samples. Needs the Apple Commander
+# program available at http://applecommander.sourceforge.net/ and a template
+# disk named 'prodos.dsk'.
+
+define DSK_WRITE_BIN_recipe
+
+$(if $(findstring BF00,$(LDFLAGS_$(notdir $(file))_$(SYS))), \
+ java -jar $(AC) -p $@ $(notdir $(file)).system sys <$(TARGET_PATH)/$(SYS)/util/loader.system)
+java -jar $(AC) -cc65 $@ $(notdir $(file)) bin <$(file)
+
+endef # DSK_WRITE_BIN_recipe
+
+define DSK_WRITE_REL_recipe
+
+java -jar $(AC) -p $@ $(notdir $(file)) rel 0 <$(file)
+
+endef # DSK_WRITE_REL_recipe
+
+samples.dsk: samples
+ cp prodos.dsk $@
+ $(foreach file,$(EXELIST_$(SYS)),$(DSK_WRITE_BIN_recipe))
+ $(foreach file,$(OVERLAYLIST),$(DSK_WRITE_REL_recipe))
+ $(foreach file,$(EMD) $(MOU) $(TGI),$(DSK_WRITE_REL_recipe))
+
+# --------------------------------------------------------------------------
+# Rule to make an Atari disk with all samples. Needs the dir2atr program
+# available at http://www.horus.com/~hias/atari/ and the MyDos4534 variant
+# of dos.sys and dup.sys.
+
+define ATR_WRITE_recipe
+
+cp $(file) atr/$(notdir $(file))
+
+endef # ATR_WRITE_recipe
+
+samples.atr: samples
+ @mkdir atr
+ cp dos.sys atr/dos.sys
+ cp dup.sys atr/dup.sys
+ @$(foreach file,$(EXELIST_$(SYS)),$(ATR_WRITE_recipe))
+ @$(foreach file,$(OVERLAYLIST),$(ATR_WRITE_recipe))
+ @$(foreach file,$(EMD) $(MOU) $(TGI),$(ATR_WRITE_recipe))
+ $(DIR2ATR) -d -b MyDos4534 3200 $@ atr
+ @$(RMDIR) atr
+
+# --------------------------------------------------------------------------
+# Installation rules
+
+INSTALL = install
+samplesdir = $(prefix)/share/cc65
+
+install:
+ $(if $(prefix),,$(error variable `prefix' must be set))
+ $(INSTALL) -d $(DESTDIR)$(samplesdir)
+ $(INSTALL) -d $(DESTDIR)$(samplesdir)/geos
+ $(INSTALL) -d $(DESTDIR)$(samplesdir)/tutorial
+ $(INSTALL) -m0644 *.* $(DESTDIR)$(samplesdir)
+ $(INSTALL) -m0644 README $(DESTDIR)$(samplesdir)
+ $(INSTALL) -m0644 Makefile $(DESTDIR)$(samplesdir)
+ $(INSTALL) -m0644 geos/*.* $(DESTDIR)$(samplesdir)/geos
+ $(INSTALL) -m0644 tutorial/*.* $(DESTDIR)$(samplesdir)/tutorial
+
+# --------------------------------------------------------------------------
+# Packaging rules
-samples.d64: all
- @$(C1541) -format samples,AA d64 $@ > /dev/null
- @for exe in $(EXELIST); do\
- $(C1541) -attach $@ -write $$exe > /dev/null || exit $$?;\
- done
- @for mod in $(TGI) $(MOUS); do\
- $(C1541) -attach $@ -write $$mod > /dev/null || exit $$?;\
- done
+zip:
+ @cd .. && zip -r cc65 samples/
# --------------------------------------------------------------------------
# Clean-up rules
-.PHONY: clean
-clean:
- $(RM) *~ *.map *.o *.s *.lbl
+mostlyclean:
+ @$(DEL) *.map *.o *.s 2>$(NULLDEV)
-.PHONY: zap
-zap: clean
- $(RM) $(EXELIST) samples.d64
- $(RM) multdemo.? ovrldemo.?
+clean: mostlyclean
+ @$(DEL) $(EXELIST_$(SYS)) $(DISK_$(SYS)) 2>$(NULLDEV)
+ @$(DEL) multdemo.? ovrldemo.? 2>$(NULLDEV)
Please note:
* The supplied makefile needs GNU make. It works out of the box on Linux
- and similar systems. If you're using Windows, you will have to compile
- the programs manually.
-
- * The makefile specifies the C64 as the default target platform, because all
- but one
- of the programs run on this platform. When compiling for another platform,
- you will have to change the line that specifies the target system at the
- top of the makefile.
+ and similar systems. If you're using Windows, consider installing Cygwin.
+
+ * The makefile specifies the C64 as the default target system, because all
+ but one of the programs run on this platform. When compiling for another
+ system, you will have to change the line that specifies the target system
+ at the top of the makefile, specify the system with SYS=<target> on the
+ make command line or set a SYS env var.
List of supplied sample programs:
/* This prompt fits on the VIC-20's narrow screen.
*/
- PRINT("Type characters to see\r\ntheir hexadecimal code\r\nnumbers:\r\n\n");
+ PRINT("Type characters to see\r\ntheir hexadecimal code\r\nnumbers - 'Q' quits:\r\n\n");
screensize(&width, &height); /* get the screen's dimensions */
width /= 6; /* get number of codes on a line */
cursor(true);
--- /dev/null
+/*****************************************************************************/
+/* */
+/* Atari VCS 2600 sample C program */
+/* */
+/* Florent Flament (contact@florentflament.com), 2017 */
+/* */
+/*****************************************************************************/
+
+#include <atari2600.h>
+
+// PAL Timings
+// Roughly computed based on Stella Programmer's guide (Steve Wright)
+// scanlines count per section.
+#define VBLANK_TIM64 51 // 45 lines * 76 cycles/line / 64 cycles/tick
+#define KERNAL_T1024 17 // 228 lines * 76 cycles/line / 1024 cycles/tick
+#define OVERSCAN_TIM64 42 // 36 lines * 76 cycles/line / 64 cycles/tick
+
+// Testing memory zones
+const unsigned char rodata_v[] = "Hello!";
+unsigned char data_v = 0x77;
+unsigned char bss_v;
+
+void main(void) {
+ unsigned char color = 0x79; // Stack variable
+ bss_v = 0x88; // Testing BSS variable
+
+ for/*ever*/(;;) {
+ // Vertical Sync signal
+ TIA.vsync = 0x02;
+ TIA.wsync = 0x00;
+ TIA.wsync = 0x00;
+ TIA.wsync = 0x00;
+ TIA.vsync = 0x00;
+
+ // Vertical Blank timer setting
+ RIOT.tim64t = VBLANK_TIM64;
+
+ // Doing frame computation during blank
+ TIA.colubk = color++; // Update color
+
+ // Wait for end of Vertical Blank
+ while (RIOT.timint == 0) {}
+ TIA.wsync = 0x00;
+ TIA.vblank = 0x00; // Turn on beam
+
+ // Display frame
+ RIOT.t1024t = KERNAL_T1024;
+ while (RIOT.timint == 0) {}
+ TIA.wsync = 0x00;
+ TIA.vblank = 0x02; // Turn off beam
+
+ // Overscan
+ RIOT.tim64t = OVERSCAN_TIM64;
+ while (RIOT.timint == 0) {}
+ }
+}
#include <conio.h>
#include <ctype.h>
#include <errno.h>
+#include <cc65.h>
#include <dio.h>
clrscr ();
screensize (&ScreenX, &ScreenY);
+ /* Allow user to read exit messages */
+ if (doesclrscrafterexit ()) {
+ atexit ((void (*)) cgetc);
+ }
+
cputs ("Floppy Disk Copy\r\n");
chline (16);
cputs ("\r\n");
#include <stdio.h>
-#include <conio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <device.h>
#include <dirent.h>
+#include <cc65.h>
void printdir (char *newdir)
device = getnextdevice (device);
}
- cgetc ();
+ if (doesclrscrafterexit ()) {
+ getchar ();
+ }
}
#include <string.h>
#include <zlib.h>
+#ifdef __CC65__
+#include <stdlib.h>
+#include <cc65.h>
+#endif
+
#ifndef __CC65__
/*
** Emulate inflatemem() if using original zlib.
FILE* fp;
unsigned length;
+#ifdef __CC65__
+ /* allow user to read exit messages */
+ if (doesclrscrafterexit()) {
+ atexit((void (*)) getchar);
+ }
+#endif /* __CC65__ */
+
/* read GZIP file */
puts("GZIP file name:");
fp = fopen(get_fname(), "rb");
{
unsigned char XSize, YSize;
- /* Set screen colors, hide the cursor */
- textcolor (COLOR_WHITE);
- bordercolor (COLOR_BLACK);
- bgcolor (COLOR_BLACK);
- cursor (0);
+ /* Set screen colors */
+ (void) textcolor (COLOR_WHITE);
+ (void) bordercolor (COLOR_BLACK);
+ (void) bgcolor (COLOR_BLACK);
/* Clear the screen, put cursor in upper left corner */
clrscr ();
#else
/* Wait for the user to press a key */
- (void) cgetc ();
+ cgetc ();
#endif
#include <time.h>
#include <conio.h>
#include <tgi.h>
+#include <cc65.h>
register signed short xs, ys, xx, yy;
register signed short x, y;
- /* calc stepwidth */
+ /* Calc stepwidth */
xs = ((x2 - x1) / (SCREEN_X));
ys = ((y2 - y1) / (SCREEN_Y));
xx = x1;
for (x = 0; x < (SCREEN_X); x++) {
xx += xs;
- /* do iterations */
+ /* Do iterations */
r = 0;
i = 0;
for (count = 0; (count < maxiterations) &&
if (count == maxiterations) {
tgi_setcolor (0);
} else {
- if (MAXCOL == 2)
+ if (MAXCOL == 2) {
tgi_setcolor (1);
- else
+ } else {
tgi_setcolor (count % MAXCOL);
+ }
}
- /* set pixel */
+ /* Set pixel */
tgi_setpixel (x, y);
}
}
if (err != TGI_ERR_OK) {
cprintf ("Error #%d initializing graphics.\r\n%s\r\n",
err, tgi_geterrormsg (err));
+ if (doesclrscrafterexit ()) {
+ cgetc ();
+ }
exit (EXIT_FAILURE);
};
cprintf ("ok.\n\r");
t = clock ();
- /* calc mandelbrot set */
+ /* Calc mandelbrot set */
mandelbrot (tofp (-2), tofp (-2), tofp (2), tofp (2));
t = clock () - t;
/* Fetch the character from the keyboard buffer and discard it */
- (void) cgetc ();
+ cgetc ();
- /* shut down gfx mode and return to textmode */
+ /* Shut down gfx mode and return to textmode */
tgi_done ();
/* Calculate stats */
/* Output stats */
cprintf ("time : %lu.%us\n\r", sec, sec10);
- /* Wait for a key, then end */
- cputs ("Press any key when done...\n\r");
- (void) cgetc ();
+ if (doesclrscrafterexit ()) {
+ /* Wait for a key, then end */
+ cputs ("Press any key when done...\n\r");
+ cgetc ();
+ }
/* Done */
return EXIT_SUCCESS;
#include <conio.h>
#include <ctype.h>
#include <dbg.h>
+#include <cc65.h>
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
/* Wait for a key-press, so that some platforms can show the error
** message before they remove the current screen.
*/
- cgetc();
+ if (doesclrscrafterexit ()) {
+ cgetc ();
+ }
exit (EXIT_FAILURE);
}
}
#include <string.h>
-#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <em.h>
+#include <cc65.h>
#ifndef __CBM__
#include <fcntl.h>
#include <unistd.h>
#else
+#include <cbm.h>
#include <device.h>
#endif
}
log ("Press any key...");
- cgetc ();
+ getchar ();
if (loadoverlay (1)) {
log ("Calling overlay 1 from main");
foobar ();
}
- log ("Press any key...");
- cgetc ();
+ if (doesclrscrafterexit ()) {
+ log ("Press any key...");
+ getchar ();
+ }
}
#include <stdio.h>
-#include <conio.h>
+#include <cc65.h>
#ifndef __CBM__
#include <fcntl.h>
#include <unistd.h>
#else
+#include <cbm.h>
#include <device.h>
#endif
foobar ();
}
- cgetc ();
+ if (doesclrscrafterexit ()) {
+ getchar ();
+ }
}
#include <stdlib.h>
#include <time.h>
#include <conio.h>
+#include <cc65.h>
gotoxy (0, 1); cprintf ("frames: %lu", f);
gotoxy (0, 2); cprintf ("fps : %lu.%u", fps, fps10);
- /* Wait for a key, then end */
- cputsxy (0, 4, "Press any key when done...");
- (void) cgetc ();
+ if (doesclrscrafterexit ()) {
+ cputsxy (0, 4, "Press any key when done...");
+ (void) cgetc ();
+ }
/* Done */
return EXIT_SUCCESS;
}
-
-
unsigned char Error = tgi_geterror ();
if (Error != TGI_ERR_OK) {
printf ("%s: %d\n", S, Error);
+ if (doesclrscrafterexit ()) {
+ cgetc ();
+ }
exit (EXIT_FAILURE);
}
}
CMD_EXE = 1
endif
-PROGS = ar65 \
- ca65 \
- cc65 \
- cl65 \
- co65 \
- da65 \
- grc65 \
- ld65 \
- od65 \
- sim65 \
+PROGS = ar65 \
+ ca65 \
+ cc65 \
+ chrcvt65 \
+ cl65 \
+ co65 \
+ da65 \
+ grc65 \
+ ld65 \
+ od65 \
+ sim65 \
sp65
.PHONY: all mostlyclean clean install zip avail unavail bin $(PROGS)
CA65_INC = $(datadir)/asminc
CC65_INC = $(datadir)/include
+CL65_TGT = $(datadir)/target
LD65_LIB = $(datadir)/lib
LD65_OBJ = $(datadir)/lib
LD65_CFG = $(datadir)/cfg
CFLAGS += -MMD -MP -O -I common \
-Wall -Wextra -Wno-char-subscripts $(USER_CFLAGS) \
- -DGIT_SHA=$(GIT_SHA) -DCA65_INC=$(CA65_INC) -DCC65_INC=$(CC65_INC) \
+ -DCA65_INC=$(CA65_INC) -DCC65_INC=$(CC65_INC) -DCL65_TGT=$(CL65_TGT) \
-DLD65_LIB=$(LD65_LIB) -DLD65_OBJ=$(LD65_OBJ) -DLD65_CFG=$(LD65_CFG)
+ -DGIT_SHA=$(GIT_SHA)
LDLIBS += -lm
break;
case 'V':
- fprintf (stderr, "ar65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
break;
default:
CalcOverallIfCond ();
break;
+ case TOK_IFP4510:
+ D = AllocIf (".IFP4510", 1);
+ NextTok ();
+ if (IfCond) {
+ SetIfCond (D, GetCPU() == CPU_4510);
+ }
+ ExpectSep ();
+ CalcOverallIfCond ();
+ break;
+
case TOK_IFP816:
D = AllocIf (".IFP816", 1);
NextTok ();
case TOK_IFNDEF:
case TOK_IFNREF:
case TOK_IFP02:
+ case TOK_IFP4510:
case TOK_IFP816:
case TOK_IFPC02:
case TOK_IFPSC02:
#include "expr.h"
#include "instr.h"
#include "nexttok.h"
+#include "global.h"
/* Parse an effective address, return the result in A */
{
unsigned long Restrictions;
+ token_t IndirectEnter;
+ token_t IndirectLeave;
+ const char* IndirectExpect;
+
+ /* Choose syntax for indirection */
+ if (BracketAsIndirect) {
+ IndirectEnter = TOK_LBRACK;
+ IndirectLeave = TOK_RBRACK;
+ IndirectExpect = "']' expected";
+ } else {
+ IndirectEnter = TOK_LPAREN;
+ IndirectLeave = TOK_RPAREN;
+ IndirectExpect = "')' expected";
+ }
/* Clear the output struct */
A->AddrModeSet = 0;
NextTok ();
A->AddrModeSet = AM65_ACCU;
- } else if (CurTok.Tok == TOK_LBRACK) {
-
- /* [dir] or [dir],y */
- NextTok ();
- A->Expr = Expression ();
- Consume (TOK_RBRACK, "']' expected");
- if (CurTok.Tok == TOK_COMMA) {
- /* [dir],y */
- NextTok ();
- Consume (TOK_Y, "`Y' expected");
- A->AddrModeSet = AM65_DIR_IND_LONG_Y;
- } else {
- /* [dir] */
- A->AddrModeSet = AM65_DIR_IND_LONG | AM65_ABS_IND_LONG;
- }
-
- } else if (CurTok.Tok == TOK_LPAREN) {
+ } else if (CurTok.Tok == IndirectEnter) {
/* One of the indirect modes */
NextTok ();
/* (adr,x) */
NextTok ();
A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND;
- ConsumeRParen ();
+ Consume (IndirectLeave, IndirectExpect);
} else if (CurTok.Tok == TOK_S) {
/* (rel,s),y */
NextTok ();
A->AddrModeSet = AM65_STACK_REL_IND_Y;
- ConsumeRParen ();
+ Consume (IndirectLeave, IndirectExpect);
ConsumeComma ();
Consume (TOK_Y, "`Y' expected");
} else {
} else {
- /* (adr) or (adr),y */
- ConsumeRParen ();
+ /* (adr), (adr),y or (adr),z */
+ Consume (IndirectLeave, IndirectExpect);
if (CurTok.Tok == TOK_COMMA) {
/* (adr),y */
NextTok ();
- Consume (TOK_Y, "`Y' expected");
- A->AddrModeSet = AM65_DIR_IND_Y;
+ switch (CurTok.Tok) {
+ case TOK_Z:
+ /* only set by scanner.c if in 4510-mode */
+ NextTok ();
+ A->AddrModeSet = AM65_DIR_IND;
+ break;
+ default:
+ Consume (TOK_Y, "`Y' expected");
+ A->AddrModeSet = AM65_DIR_IND_Y;
+ break;
+ }
} else {
/* (adr) */
- A->AddrModeSet = AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND;
+ A->AddrModeSet = (CPU == CPU_4510) ? AM65_ABS_IND
+ : AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND;
}
}
+ } else if (CurTok.Tok == TOK_LBRACK) {
+
+ /* Never executed if BracketAsIndirect feature is enabled. */
+ /* [dir] or [dir],y */
+ NextTok ();
+ A->Expr = Expression ();
+ Consume (TOK_RBRACK, "']' expected");
+ if (CurTok.Tok == TOK_COMMA) {
+ /* [dir],y */
+ NextTok ();
+ Consume (TOK_Y, "`Y' expected");
+ A->AddrModeSet = AM65_DIR_IND_LONG_Y;
+ } else {
+ /* [dir] */
+ A->AddrModeSet = AM65_DIR_IND_LONG | AM65_ABS_IND_LONG;
+ }
+
} else {
/* Remaining stuff:
break;
case LI_TYPE_EXT:
- Msg = "Assembler code generated from this line";
+ Msg = "Assembly code generated from this line";
break;
case LI_TYPE_MACRO:
"force_range",
"underline_in_numbers",
"addrsize",
+ "bracket_as_indirect",
};
case FEAT_FORCE_RANGE: ForceRange = 1; break;
case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break;
case FEAT_ADDRSIZE: AddrSize = 1; break;
+ case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = 1; break;
default: /* Keep gcc silent */ break;
}
FEAT_FORCE_RANGE,
FEAT_UNDERLINE_IN_NUMBERS,
FEAT_ADDRSIZE,
+ FEAT_BRACKET_AS_INDIRECT,
/* Special value: Number of features available */
FEAT_COUNT
unsigned char ForceRange = 0; /* Force values into expected range */
unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */
unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */
+unsigned char BracketAsIndirect = 0; /* Use '[]' not '()' for indirection */
extern unsigned char ForceRange; /* Force values into expected range */
extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */
extern unsigned char AddrSize; /* Allow .ADDRSIZE function */
+extern unsigned char BracketAsIndirect; /* Use '[]' not '()' for indirection */
static void PutPCRel16 (const InsDesc* Ins);
/* Handle branches with an 16 bit distance and PER */
+static void PutPCRel4510 (const InsDesc* Ins);
+/* Handle branches with a 16 bit distance for 4510 */
+
static void PutBlockMove (const InsDesc* Ins);
/* Handle the blockmove instructions (65816) */
static void PutAll (const InsDesc* Ins);
/* Handle all other instructions */
+static void Put4510 (const InsDesc* Ins);
+/* Handle instructions of 4510 not matching any EATab */
+
static void PutSweet16 (const InsDesc* Ins);
/* Handle a generic sweet16 instruction */
/* Instruction table for the 65C02 */
static const struct {
unsigned Count;
- InsDesc Ins[98];
+ InsDesc Ins[100];
} InsTab65C02 = {
sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]),
{
{ "SMB6", 0x0000004, 0xE7, 1, PutAll },
{ "SMB7", 0x0000004, 0xF7, 1, PutAll },
{ "STA", 0x000A66C, 0x80, 0, PutAll },
+ { "STP", 0x0000001, 0xdb, 0, PutAll },
{ "STX", 0x000010c, 0x82, 1, PutAll },
{ "STY", 0x000002c, 0x80, 1, PutAll },
{ "STZ", 0x000006c, 0x04, 5, PutAll },
{ "TSX", 0x0000001, 0xba, 0, PutAll },
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
- { "TYA", 0x0000001, 0x98, 0, PutAll }
+ { "TYA", 0x0000001, 0x98, 0, PutAll },
+ { "WAI", 0x0000001, 0xcb, 0, PutAll }
+ }
+};
+
+/* Instruction table for the 4510 */
+static const struct {
+ unsigned Count;
+ InsDesc Ins[133];
+} InsTab4510 = {
+ sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]),
+ {
+ { "ADC", 0x080A66C, 0x60, 0, PutAll },
+ { "AND", 0x080A66C, 0x20, 0, PutAll },
+ { "ASL", 0x000006e, 0x02, 1, PutAll },
+ { "ASR", 0x0000026, 0x43, 0, Put4510 },
+ { "ASW", 0x0000008, 0xcb, 6, PutAll },
+ { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
+ { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
+ { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
+ { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
+ { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
+ { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
+ { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
+ { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
+ { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
+ { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
+ { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
+ { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
+ { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
+ { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
+ { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
+ { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
+ { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
+ { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
+ { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
+ { "BIT", 0x0A0006C, 0x00, 2, PutAll },
+ { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
+ { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
+ { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
+ { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
+ { "BRK", 0x0000001, 0x00, 0, PutAll },
+ { "BSR", 0x0040000, 0x63, 0, PutPCRel4510 },
+ { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
+ { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
+ { "CLC", 0x0000001, 0x18, 0, PutAll },
+ { "CLD", 0x0000001, 0xd8, 0, PutAll },
+ { "CLE", 0x0000001, 0x02, 0, PutAll },
+ { "CLI", 0x0000001, 0x58, 0, PutAll },
+ { "CLV", 0x0000001, 0xb8, 0, PutAll },
+ { "CMP", 0x080A66C, 0xc0, 0, PutAll },
+ { "CPX", 0x080000C, 0xe0, 1, PutAll },
+ { "CPY", 0x080000C, 0xc0, 1, PutAll },
+ { "CPZ", 0x080000C, 0xd0, 1, Put4510 },
+ { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
+ { "DEC", 0x000006F, 0x00, 3, PutAll },
+ { "DEW", 0x0000004, 0xc3, 9, PutAll },
+ { "DEX", 0x0000001, 0xca, 0, PutAll },
+ { "DEY", 0x0000001, 0x88, 0, PutAll },
+ { "DEZ", 0x0000001, 0x3B, 0, PutAll },
+ { "EOM", 0x0000001, 0xea, 0, PutAll },
+ { "EOR", 0x080A66C, 0x40, 0, PutAll },
+ { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
+ { "INC", 0x000006f, 0x00, 4, PutAll },
+ { "INW", 0x0000004, 0xe3, 9, PutAll },
+ { "INX", 0x0000001, 0xe8, 0, PutAll },
+ { "INY", 0x0000001, 0xc8, 0, PutAll },
+ { "INZ", 0x0000001, 0x1B, 0, PutAll },
+ { "JMP", 0x0010808, 0x4c, 6, PutAll },
+ { "JSR", 0x0010808, 0x20, 7, Put4510 },
+ { "LBCC", 0x0040000, 0x93, 0, PutPCRel4510 },
+ { "LBCS", 0x0040000, 0xb3, 0, PutPCRel4510 },
+ { "LBEQ", 0x0040000, 0xf3, 0, PutPCRel4510 },
+ { "LBMI", 0x0040000, 0x33, 0, PutPCRel4510 },
+ { "LBNE", 0x0040000, 0xd3, 0, PutPCRel4510 },
+ { "LBPL", 0x0040000, 0x13, 0, PutPCRel4510 },
+ { "LBRA", 0x0040000, 0x83, 0, PutPCRel4510 },
+ { "LBVC", 0x0040000, 0x53, 0, PutPCRel4510 },
+ { "LBVS", 0x0040000, 0x73, 0, PutPCRel4510 },
+ { "LDA", 0x090A66C, 0xa0, 0, Put4510 },
+ { "LDX", 0x080030C, 0xa2, 1, PutAll },
+ { "LDY", 0x080006C, 0xa0, 1, PutAll },
+ { "LDZ", 0x0800048, 0xa3, 1, Put4510 },
+ { "LSR", 0x000006F, 0x42, 1, PutAll },
+ { "MAP", 0x0000001, 0x5C, 0, PutAll },
+ { "NEG", 0x0000001, 0x42, 0, PutAll },
+ { "NOP", 0x0000001, 0xea, 0, PutAll }, /* == EOM */
+ { "ORA", 0x080A66C, 0x00, 0, PutAll },
+ { "PHA", 0x0000001, 0x48, 0, PutAll },
+ { "PHD", 0x8000008, 0xf4, 1, PutAll }, /* == PHW */
+ { "PHP", 0x0000001, 0x08, 0, PutAll },
+ { "PHW", 0x8000008, 0xf4, 1, PutAll },
+ { "PHX", 0x0000001, 0xda, 0, PutAll },
+ { "PHY", 0x0000001, 0x5a, 0, PutAll },
+ { "PHZ", 0x0000001, 0xdb, 0, PutAll },
+ { "PLA", 0x0000001, 0x68, 0, PutAll },
+ { "PLP", 0x0000001, 0x28, 0, PutAll },
+ { "PLX", 0x0000001, 0xfa, 0, PutAll },
+ { "PLY", 0x0000001, 0x7a, 0, PutAll },
+ { "PLZ", 0x0000001, 0xfb, 0, PutAll },
+ { "RMB0", 0x0000004, 0x07, 1, PutAll },
+ { "RMB1", 0x0000004, 0x17, 1, PutAll },
+ { "RMB2", 0x0000004, 0x27, 1, PutAll },
+ { "RMB3", 0x0000004, 0x37, 1, PutAll },
+ { "RMB4", 0x0000004, 0x47, 1, PutAll },
+ { "RMB5", 0x0000004, 0x57, 1, PutAll },
+ { "RMB6", 0x0000004, 0x67, 1, PutAll },
+ { "RMB7", 0x0000004, 0x77, 1, PutAll },
+ { "ROL", 0x000006F, 0x22, 1, PutAll },
+ { "ROR", 0x000006F, 0x62, 1, PutAll },
+ { "ROW", 0x0000008, 0xeb, 6, PutAll },
+ { "RTI", 0x0000001, 0x40, 0, PutAll },
+ { "RTN", 0x0800000, 0x62, 1, PutAll },
+ { "RTS", 0x0000001, 0x60, 0, PutAll },
+ { "SBC", 0x080A66C, 0xe0, 0, PutAll },
+ { "SEC", 0x0000001, 0x38, 0, PutAll },
+ { "SED", 0x0000001, 0xf8, 0, PutAll },
+ { "SEE", 0x0000001, 0x03, 0, PutAll },
+ { "SEI", 0x0000001, 0x78, 0, PutAll },
+ { "SMB0", 0x0000004, 0x87, 1, PutAll },
+ { "SMB1", 0x0000004, 0x97, 1, PutAll },
+ { "SMB2", 0x0000004, 0xA7, 1, PutAll },
+ { "SMB3", 0x0000004, 0xB7, 1, PutAll },
+ { "SMB4", 0x0000004, 0xC7, 1, PutAll },
+ { "SMB5", 0x0000004, 0xD7, 1, PutAll },
+ { "SMB6", 0x0000004, 0xE7, 1, PutAll },
+ { "SMB7", 0x0000004, 0xF7, 1, PutAll },
+ { "STA", 0x010A66C, 0x80, 0, Put4510 },
+ { "STX", 0x000030c, 0x82, 1, Put4510 },
+ { "STY", 0x000006c, 0x80, 1, Put4510 },
+ { "STZ", 0x000006c, 0x04, 5, PutAll },
+ { "TAB", 0x0000001, 0x5b, 0, PutAll },
+ { "TAX", 0x0000001, 0xaa, 0, PutAll },
+ { "TAY", 0x0000001, 0xa8, 0, PutAll },
+ { "TAZ", 0x0000001, 0x4b, 0, PutAll },
+ { "TBA", 0x0000001, 0x7b, 0, PutAll },
+ { "TRB", 0x000000c, 0x10, 1, PutAll },
+ { "TSB", 0x000000c, 0x00, 1, PutAll },
+ { "TSX", 0x0000001, 0xba, 0, PutAll },
+ { "TSY", 0x0000001, 0x0b, 0, PutAll },
+ { "TXA", 0x0000001, 0x8a, 0, PutAll },
+ { "TXS", 0x0000001, 0x9a, 0, PutAll },
+ { "TYA", 0x0000001, 0x98, 0, PutAll },
+ { "TYS", 0x0000001, 0x2b, 0, PutAll },
+ { "TZA", 0x0000001, 0x6b, 0, PutAll },
}
};
(const InsTable*) &InsTabSweet16,
(const InsTable*) &InsTabHuC6280,
0, /* Mitsubishi 740 */
+ (const InsTable*) &InsTab4510,
};
const InsTable* InsTab = (const InsTable*) &InsTab6502;
0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 1 */
0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x80
+ 0x00, 0x00, 0x80, 0x00
},
{ /* Table 2 */
0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 3 */
0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 4 */
0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 5 */
0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 6 */
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x90
+ 0x00, 0x00, 0x90, 0x00
},
- { /* Table 7 */
+ { /* Table 7 (Subroutine opcodes) */
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 8 */
0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 9 */
0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 10 (NOPs) */
0xea, 0x00, 0x04, 0x0c, 0x00, 0x14, 0x1c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
},
{ /* Table 11 (LAX) */
0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x80
+ 0x00, 0x00, 0x80, 0x00
},
};
2, /* Blockmove (65816) */
7, /* Block transfer (HuC6280) */
2, /* Absolute Indirect long */
+ 2, /* Immidiate word */
};
/* Table that encodes the additional bytes for each SWEET16 instruction */
** limit the expression to the maximum possible value.
*/
if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX ||
- A->AddrMode == AM65I_IMM_IMPLICIT) {
+ A->AddrMode == AM65I_IMM_IMPLICIT || A->AddrMode == AM65I_IMM_IMPLICIT_WORD) {
if (ForceRange && A->Expr) {
A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]);
}
+static void PutPCRel4510 (const InsDesc* Ins)
+/* Handle branches with a 16 bit distance */
+{
+ /* 16 bit branch opcode is 8 bit branch opcode or'ed with 0x03 */
+ EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 2);
+}
+
+
static void PutBlockMove (const InsDesc* Ins)
/* Handle the blockmove instructions (65816) */
{
+static void Put4510 (const InsDesc* Ins)
+/* Handle all other instructions, with modifications for 4510 */
+{
+ /* The 4510 uses all 256 possible opcodes, so the last ones were crammed
+ ** in where an opcode was still undefined. As a result, some of those
+ ** don't follow any rules for encoding the addressmodes. So the EATab
+ ** approach does not work always. In this function, the wrongly calculated
+ ** opcode is replaced by the correct one "on the fly". Suggestions for a
+ ** better approach are welcome.
+ **
+ ** These are:
+ ** $47 -> $44 : ASR $12
+ ** $57 -> $54 : ASR $12,X
+ ** $93 -> $82 : STA ($12,SP),Y
+ ** $9c -> $8b : STY $1234,X
+ ** $9e -> $9b : STX $1234,Y
+ ** $af -> $ab : LDZ $1234
+ ** $bf -> $bb : LDZ $1234,X
+ ** $b3 -> $e2 : LDA ($12,SP),Y
+ ** $d0 -> $c2 : CPZ #$00
+ ** $fc -> $23 : JSR ($1234,X)
+ */
+ EffAddr A;
+
+ /* Evaluate the addressing mode used */
+ if (EvalEA (Ins, &A)) {
+ switch (A.Opcode) {
+ case 0x47: A.Opcode = 0x44; break;
+ case 0x57: A.Opcode = 0x54; break;
+ case 0x93: A.Opcode = 0x82; break;
+ case 0x9C: A.Opcode = 0x8B; break;
+ case 0x9E: A.Opcode = 0x9B; break;
+ case 0xAF: A.Opcode = 0xAB; break;
+ case 0xBF: A.Opcode = 0xBB; break;
+ case 0xB3: A.Opcode = 0xE2; break;
+ case 0xD0: A.Opcode = 0xC2; break;
+ case 0xFC: A.Opcode = 0x23; break;
+ default: /* Keep opcode as it is */ break;
+ }
+
+ /* No error, output code */
+ EmitCode (&A);
+ }
+}
+
+
+
/*****************************************************************************/
/* Handler functions for SWEET16 */
/*****************************************************************************/
#define AM65_BLOCKMOVE 0x01000000UL
#define AM65_BLOCKXFER 0x02000000UL
#define AM65_ABS_IND_LONG 0x04000000UL
+#define AM65_IMM_IMPLICIT_WORD 0x08000000UL /* PHW #$1234 (4510 only) */
/* Bitmask for all ZP operations that have correspondent ABS ops */
#define AM65_SET_ZP (AM65_DIR | AM65_DIR_X | AM65_DIR_Y | AM65_DIR_IND | AM65_DIR_X_IND)
#define AM65_ALL_FAR (AM65_ABS_LONG | AM65_ABS_LONG_X)
/* Bitmask for all immediate operations */
-#define AM65_ALL_IMM (AM65_IMM_ACCU | AM65_IMM_INDEX | AM65_IMM_IMPLICIT)
+#define AM65_ALL_IMM (AM65_IMM_ACCU | AM65_IMM_INDEX | AM65_IMM_IMPLICIT | AM65_IMM_IMPLICIT_WORD)
/* Bit numbers and count */
#define AM65I_IMM_ACCU 21
#define AM65I_IMM_INDEX 22
#define AM65I_IMM_IMPLICIT 23
-#define AM65I_COUNT 27
+#define AM65I_IMM_IMPLICIT_WORD 27
+#define AM65I_COUNT 28
/* Start a new line using the current line info */
AsmLineInfo = StartLine (&CurTok.Pos, LI_TYPE_ASM, 0);
+
+ /* If the first LineInfo in the list came from a .dbg line, then we want
+ ** errors and warnings to show it as an additional note, not as the primary
+ ** line. Therefore, swap the first two LineInfo items.
+ */
+ if (GetLineInfoType (CollAtUnchecked (&CurLineInfo, 0)) == LI_TYPE_EXT) {
+ CollMove (&CurLineInfo, 1, 0);
+ }
}
AbEnd ("Cannot use `module' as a target for the assembler");
break;
+ case TGT_ATARI2600:
+ NewSymbol ("__ATARI2600__", 1);
+ break;
+
case TGT_ATARI5200:
NewSymbol ("__ATARI5200__", 1);
break;
CBMSystem ("__C64__");
break;
+ case TGT_C65:
+ CBMSystem ("__C65__");
+ break;
+
case TGT_VIC20:
CBMSystem ("__VIC20__");
break;
const char* Arg attribute ((unused)))
/* Print the assembler version */
{
- fprintf (stderr, "ca65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
static void DoCharMap (void)
-/* Allow custome character mappings */
+/* Allow custom character mappings */
{
long Index;
long Code;
/* Read the index as numerical value */
Index = ConstExpression ();
- if (Index <= 0 || Index > 255) {
+ if (Index < 0 || Index > 255) {
/* Value out of range */
- ErrorSkip ("Range error");
+ ErrorSkip ("Index range error");
return;
}
Code = ConstExpression ();
if (Code < 0 || Code > 255) {
/* Value out of range */
- ErrorSkip ("Range error");
+ ErrorSkip ("Code range error");
return;
}
+static void DoP4510 (void)
+/* Switch to 4510 CPU */
+{
+ SetCPU (CPU_4510);
+}
+
+
+
static void DoPageLength (void)
/* Set the page length for the listing */
{
{ ccKeepToken, DoConditionals }, /* .IFNDEF */
{ ccKeepToken, DoConditionals }, /* .IFNREF */
{ ccKeepToken, DoConditionals }, /* .IFP02 */
+ { ccKeepToken, DoConditionals }, /* .IFP4510 */
{ ccKeepToken, DoConditionals }, /* .IFP816 */
{ ccKeepToken, DoConditionals }, /* .IFPC02 */
{ ccKeepToken, DoConditionals }, /* .IFPSC02 */
{ ccNone, DoOrg },
{ ccNone, DoOut },
{ ccNone, DoP02 },
+ { ccNone, DoP4510 },
{ ccNone, DoP816 },
{ ccNone, DoPageLength },
{ ccNone, DoUnexpected }, /* .PARAMCOUNT */
{ ".IFNDEF", TOK_IFNDEF },
{ ".IFNREF", TOK_IFNREF },
{ ".IFP02", TOK_IFP02 },
+ { ".IFP4510", TOK_IFP4510 },
{ ".IFP816", TOK_IFP816 },
{ ".IFPC02", TOK_IFPC02 },
{ ".IFPSC02", TOK_IFPSC02 },
{ ".ORG", TOK_ORG },
{ ".OUT", TOK_OUT },
{ ".P02", TOK_P02 },
+ { ".P4510", TOK_P4510 },
{ ".P816", TOK_P816 },
{ ".PAGELEN", TOK_PAGELENGTH },
{ ".PAGELENGTH", TOK_PAGELENGTH },
/* If we come here, we have a new input line. To avoid problems
** with strange line terminators, remove all whitespace from the
- ** end of the line, the add a single newline.
+ ** end of the line, then add a single newline.
*/
Len = SB_GetLen (&S->V.File.Line);
while (Len > 0 && IsSpace (SB_AtUnchecked (&S->V.File.Line, Len-1))) {
/* Check for special names. Bail out if we have identified the type of
** the token. Go on if the token is an identifier.
*/
- if (SB_GetLen (&CurTok.SVal) == 1) {
- switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) {
-
- case 'A':
- if (C == ':') {
- NextChar ();
- CurTok.Tok = TOK_OVERRIDE_ABS;
- } else {
- CurTok.Tok = TOK_A;
- }
- return;
-
- case 'F':
- if (C == ':') {
- NextChar ();
- CurTok.Tok = TOK_OVERRIDE_FAR;
+ switch (SB_GetLen (&CurTok.SVal)) {
+ case 1:
+ switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) {
+
+ case 'A':
+ if (C == ':') {
+ NextChar ();
+ CurTok.Tok = TOK_OVERRIDE_ABS;
+ } else {
+ CurTok.Tok = TOK_A;
+ }
return;
- }
- break;
- case 'S':
- if (CPU == CPU_65816) {
- CurTok.Tok = TOK_S;
- return;
- }
- break;
+ case 'F':
+ if (C == ':') {
+ NextChar ();
+ CurTok.Tok = TOK_OVERRIDE_FAR;
+ return;
+ }
+ break;
- case 'X':
- CurTok.Tok = TOK_X;
- return;
+ case 'S':
+ if ((CPU == CPU_4510) || (CPU == CPU_65816)) {
+ CurTok.Tok = TOK_S;
+ return;
+ }
+ break;
- case 'Y':
- CurTok.Tok = TOK_Y;
- return;
+ case 'X':
+ CurTok.Tok = TOK_X;
+ return;
- case 'Z':
- if (C == ':') {
- NextChar ();
- CurTok.Tok = TOK_OVERRIDE_ZP;
+ case 'Y':
+ CurTok.Tok = TOK_Y;
return;
- }
- break;
- default:
- break;
- }
+ case 'Z':
+ if (C == ':') {
+ NextChar ();
+ CurTok.Tok = TOK_OVERRIDE_ZP;
+ return;
+ } else {
+ if (CPU == CPU_4510) {
+ CurTok.Tok = TOK_Z;
+ return;
+ }
+ }
+ break;
- } else if (CPU == CPU_SWEET16 &&
- (CurTok.IVal = Sweet16Reg (&CurTok.SVal)) >= 0) {
+ default:
+ break;
+ }
+ break;
+ case 2:
+ if ((CPU == CPU_4510) &&
+ (toupper (SB_AtUnchecked (&CurTok.SVal, 0)) == 'S') &&
+ (toupper (SB_AtUnchecked (&CurTok.SVal, 1)) == 'P')) {
- /* A sweet16 register number in sweet16 mode */
- CurTok.Tok = TOK_REG;
- return;
+ CurTok.Tok = TOK_S;
+ return;
+ }
+ /* FALL THROUGH */
+ default:
+ if (CPU == CPU_SWEET16 &&
+ (CurTok.IVal = Sweet16Reg (&CurTok.SVal)) >= 0) {
+ /* A sweet16 register number in sweet16 mode */
+ CurTok.Tok = TOK_REG;
+ return;
+ }
}
/* Check for define style macro */
TOK_A, /* A)ccumulator */
TOK_X, /* X register */
TOK_Y, /* Y register */
+ TOK_Z, /* Z register */
TOK_S, /* S register */
TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */
TOK_IFNDEF,
TOK_IFNREF,
TOK_IFP02,
+ TOK_IFP4510,
TOK_IFP816,
TOK_IFPC02,
TOK_IFPSC02,
TOK_ORG,
TOK_OUT,
TOK_P02,
+ TOK_P4510,
TOK_P816,
TOK_PAGELENGTH,
TOK_PARAMCOUNT,
{71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chrcvt65", "chrcvt65.vcxproj", "{1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
{002A366E-2863-46A8-BDDE-DDF534AAEC73}.Debug|Win32.Build.0 = Debug|Win32
{002A366E-2863-46A8-BDDE-DDF534AAEC73}.Release|Win32.ActiveCfg = Release|Win32
{002A366E-2863-46A8-BDDE-DDF534AAEC73}.Release|Win32.Build.0 = Release|Win32
+ {1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}.Debug|Win32.Build.0 = Debug|Win32
+ {1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}.Release|Win32.ActiveCfg = Release|Win32
+ {1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
/* cc65 */
#include "asmlabel.h"
#include "codegen.h"
+#include "codeseg.h"
#include "datatype.h"
#include "error.h"
#include "expr.h"
#include "function.h"
#include "litpool.h"
#include "scanner.h"
+#include "segments.h"
#include "stackptr.h"
#include "symtab.h"
#include "asmstmt.h"
/* Skip the ASM */
NextToken ();
+ /* An optional volatile qualifier disables optimization for
+ ** the entire function [same as #pragma optimize(push, off)].
+ */
+ if (CurTok.Tok == TOK_VOLATILE) {
+ /* Don't optimize the Current code Segment */
+ CS->Code->Optimize = 0;
+ NextToken ();
+ }
+
/* Need left parenthesis */
if (!ConsumeLParen ()) {
return;
#include "global.h"
#include "segments.h"
#include "stackptr.h"
+#include "stdfunc.h"
#include "textseg.h"
#include "util.h"
#include "codegen.h"
AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
}
}
AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
} else {
- /* Use the easy way here: memcpy */
+ /* Use the easy way here: memcpy() */
g_getimmed (CF_STATIC, VarLabel, 0);
AddCodeLine ("jsr pushax");
g_getimmed (CF_STATIC, InitLabel, 0);
/* List all optimization steps */
{
unsigned I;
+
+ fprintf (F, "any\n");
for (I = 0; I < OPTFUNC_COUNT; ++I) {
fprintf (F, "%s\n", OptFuncs[I]->Name);
}
/* Warn about: */
IntStack WarnConstComparison= INTSTACK(1); /* - constant comparison results */
IntStack WarnNoEffect = INTSTACK(1); /* - statements without an effect */
+IntStack WarnRemapZero = INTSTACK(1); /* - remapping character code zero */
IntStack WarnStructParam = INTSTACK(1); /* - structs passed by val */
+IntStack WarnUnknownPragma = INTSTACK(1); /* - unknown #pragmas */
IntStack WarnUnusedLabel = INTSTACK(1); /* - unused labels */
IntStack WarnUnusedParam = INTSTACK(1); /* - unused parameters */
IntStack WarnUnusedVar = INTSTACK(1); /* - unused variables */
-IntStack WarnUnknownPragma = INTSTACK(1); /* - unknown #pragmas */
/* Map the name of a warning to the intstack that holds its state */
typedef struct WarnMapEntry WarnMapEntry;
const char* Name;
};
static WarnMapEntry WarnMap[] = {
- /* Keep sorted, even if this isn't used for now */
- { &WarningsAreErrors, "error" },
+ /* Keep names sorted, even if it isn't used for now */
{ &WarnConstComparison, "const-comparison" },
+ { &WarningsAreErrors, "error" },
{ &WarnNoEffect, "no-effect" },
+ { &WarnRemapZero, "remap-zero" },
{ &WarnStructParam, "struct-param" },
{ &WarnUnknownPragma, "unknown-pragma" },
{ &WarnUnusedLabel, "unused-label" },
/* Warn about: */
extern IntStack WarnConstComparison; /* - constant comparison results */
extern IntStack WarnNoEffect; /* - statements without an effect */
+extern IntStack WarnRemapZero; /* - remapping character code zero */
extern IntStack WarnStructParam; /* - structs passed by val */
+extern IntStack WarnUnknownPragma; /* - unknown #pragmas */
extern IntStack WarnUnusedLabel; /* - unused labels */
extern IntStack WarnUnusedParam; /* - unused parameters */
extern IntStack WarnUnusedVar; /* - unused variables */
-extern IntStack WarnUnknownPragma; /* - unknown #pragmas */
AbEnd ("Cannot use `module' as a target for the compiler");
break;
+ case TGT_ATARI2600:
+ DefineNumericMacro ("__ATARI2600__", 1);
+ break;
+
case TGT_ATARI5200:
DefineNumericMacro ("__ATARI5200__", 1);
break;
const char* Arg attribute ((unused)))
/* Print the compiler version */
{
- fprintf (stderr, "cc65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
exit (EXIT_SUCCESS);
}
if (!GetNumber (B, &Index)) {
return;
}
- if (Index < 1 || Index > 255) {
- if (Index == 0) {
- /* For groepaz */
- Error ("Remapping 0 is not allowed");
- } else {
- Error ("Character index out of range");
- }
+ if (Index < 0 || Index > 255) {
+ Error ("Character index out of range");
return;
}
if (!GetNumber (B, &C)) {
return;
}
- if (C < 1 || C > 255) {
- if (C == 0) {
- /* For groepaz */
- Error ("Remapping 0 is not allowed");
- } else {
- Error ("Character code out of range");
- }
+ if (C < 0 || C > 255) {
+ Error ("Character code out of range");
return;
}
+ /* Warn about remapping character code 0x00
+ ** (except when remapping it back to itself).
+ */
+ if (Index + C != 0 && IS_Get (&WarnRemapZero)) {
+ if (Index == 0) {
+ Warning ("Remapping from 0 is dangerous with string functions");
+ }
+ else if (C == 0) {
+ Warning ("Remapping to 0 can make string functions stop unexpectedly");
+ }
+ }
+
/* Remap the character */
TgtTranslateSet ((unsigned) Index, (unsigned char) C);
}
/* */
/* */
/* */
-/* (C) 1998-2002 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2002, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
{
int C;
int HadError;
+ int Count;
/* Check for escape chars */
if (CurC == '\\') {
case '6':
case '7':
/* Octal constant */
- HadError = 0;
+ Count = 1;
C = HexVal (CurC);
- while (IsODigit (NextC)) {
- if ((C << 3) >= 256) {
- if (!HadError) {
- Error ("Octal character constant out of range");
- HadError = 1;
- }
- } else {
- C = (C << 3) | HexVal (NextC);
- }
+ while (IsODigit (NextC) && Count++ < 3) {
+ C = (C << 3) | HexVal (NextC);
NextChar ();
}
+ if (C >= 256)
+ Error ("Octal character constant out of range");
break;
default:
Error ("Illegal character constant");
+void AddCmpCodeIfSizeNot256 (const char* Code, long Size)
+/* Add a line of Assembly code that compares an index register
+** only if it isn't comparing to #<256. (If the next line
+** is "bne", then this will avoid a redundant line.)
+*/
+{
+ if (Size != 256) {
+ AddCodeLine (Code, (unsigned int)Size);
+ }
+}
+
+
+
/*****************************************************************************/
/* memcpy */
/*****************************************************************************/
if (Arg3.Expr.IVal <= 127) {
AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
g_defcodelabel (Label);
if (Reg2) {
AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
} else {
AddCodeLine ("ldy #$00");
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
g_defcodelabel (Label);
if (Reg2) {
AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
}
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
} else {
AddCodeLine ("ldx #$00");
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
AddCodeLine ("inx");
- AddCodeLine ("cpx #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
AddCodeLine ("lda (sp),y");
AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
} else {
AddCodeLine ("ldx #$00");
AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
AddCodeLine ("iny");
AddCodeLine ("inx");
- AddCodeLine ("cpx #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
AddCodeLine ("lda (sp),y");
AddCodeLine ("sta (ptr1),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
}
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
g_defcodelabel (Label);
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
/* memset returns the address, so the result is actually identical
g_defcodelabel (Label);
AddCodeLine ("sta (ptr1),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
+void AddCmpCodeIfSizeNot256 (const char* Code, long Size);
+/* Add a line of Assembly code that compares an index register
+** only if it isn't comparing to #<256. (If the next line
+** is "bne", then this will avoid a redundant line.)
+*/
+
int FindStdFunc (const char* Name);
/* Determine if the given function is a known standard function that may be
** called in a special way. If so, return the index, otherwise return -1.
/* End of stdfunc.h */
-
#endif
/* Create a loop so we may use break. */
AddLoop (ExitLabel, 0);
- /* Make sure a curly brace follows */
- if (CurTok.Tok != TOK_LCURLY) {
- Error ("`{' expected");
- }
-
- /* Parse the following statement, which will actually be a compound
- ** statement because of the curly brace at the current input position
+ /* Parse the following statement, which may actually be a compound
+ ** statement if there is a curly brace at the current input position
*/
HaveBreak = Statement (&RCurlyBrace);
/* Free the case value tree */
FreeCaseNodeColl (SwitchData.Nodes);
- /* If the case statement was (correctly) terminated by a closing curly
+ /* If the case statement was terminated by a closing curly
** brace, skip it now.
*/
if (RCurlyBrace) {
switch (TypeCmp (NewType, Expr->Type)) {
case TC_INCOMPATIBLE:
- Error ("Incompatible pointer types");
+ Error ("Incompatible pointer types at '%s'", (Expr->Sym? Expr->Sym->Name : "Unknown"));
break;
case TC_QUAL_DIFF:
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* error.c */
-/* */
-/* Error handling for the chrcvt vector font converter */
-/* */
-/* */
-/* */
-/* (C) 1998-2009, Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
-/* */
-/* */
-/* 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. */
-/* */
-/*****************************************************************************/
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "error.h"
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-void Warning (const char* Format, ...)
-/* Print a warning message */
-{
- va_list ap;
- va_start (ap, Format);
- fprintf (stderr, "Warning: ");
- vfprintf (stderr, Format, ap);
- putc ('\n', stderr);
- va_end (ap);
-}
-
-
-
-void Error (const char* Format, ...)
-/* Print an error message and die */
-{
- va_list ap;
- va_start (ap, Format);
- fprintf (stderr, "Error: ");
- vfprintf (stderr, Format, ap);
- putc ('\n', stderr);
- va_end (ap);
- exit (EXIT_FAILURE);
-}
-
-
-
-void Internal (const char* Format, ...)
-/* Print an internal error message and die */
-{
- va_list ap;
- va_start (ap, Format);
- fprintf (stderr, "Internal error: ");
- vfprintf (stderr, Format, ap);
- putc ('\n', stderr);
- va_end (ap);
- exit (EXIT_FAILURE);
-}
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* error.h */
-/* */
-/* Error handling for the chrcvt vector font converter */
-/* */
-/* */
-/* */
-/* (C) 1998-2009, Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
-/* */
-/* */
-/* 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 ERROR_H
-#define ERROR_H
-
-
-
-/* common */
-#include "attrib.h"
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-void Warning (const char* Format, ...) attribute((format(printf,1,2)));
-/* Print a warning message */
-
-void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
-/* Print an error message and die */
-
-void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
-/* Print an internal error message and die */
-
-
-
-/* End of error.h */
-
-#endif
-
-
-
+++ /dev/null
-/*****************************************************************************/
-/* */
-/* main.c */
-/* */
-/* Main program of the chrcvt vector font converter */
-/* */
-/* */
-/* */
-/* (C) 2000-2011, Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
-/* */
-/* */
-/* 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. */
-/* */
-/*****************************************************************************/
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-/* common */
-#include "cmdline.h"
-#include "fname.h"
-#include "print.h"
-#include "strbuf.h"
-#include "xmalloc.h"
-#include "version.h"
-
-/* chrcvt */
-#include "error.h"
-
-
-
-/*
-** The following is a corrected doc from the BGI font editor toolkit:
-**
-** BGI Stroke File Format
-**
-** The structure of Borland .CHR (stroke) files is as follows:
-**
-** ; offset 0h is a Borland header:
-** ;
-** HeaderSize equ 080h
-** DataSize equ (size of font file)
-** descr equ "Triplex font"
-** fname equ "TRIP"
-** MajorVersion equ 1
-** MinorVersion equ 0
-**
-** db 'PK',8,8
-** db 'BGI ',descr,' V'
-** db MajorVersion+'0'
-** db (MinorVersion / 10)+'0',(MinorVersion mod 10)+'0'
-** db ' - 19 October 1987',0DH,0AH
-** db 'Copyright (c) 1987 Borland International', 0dh,0ah
-** db 0,1ah ; null & ctrl-Z = end
-**
-** dw HeaderSize ; size of header
-** db fname ; font name
-** dw DataSize ; font file size
-** db MajorVersion,MinorVersion ; version #'s
-** db 1,0 ; minimal version #'s
-**
-** db (HeaderSize - $) DUP (0) ; pad out to header size
-**
-** At offset 80h starts data for the file:
-**
-** ; 80h '+' flags stroke file type
-** ; 81h-82h number chars in font file (n)
-** ; 83h undefined
-** ; 84h ASCII value of first char in file
-** ; 85h-86h offset to stroke definitions (8+3n)
-** ; 87h scan flag (normally 0)
-** ; 88h distance from origin to top of capital
-** ; 89h distance from origin to baseline
-** ; 8Ah distance from origin to bottom descender
-** ; 8Bh-8Fh undefined
-** ; 90h offsets to individual character definitions
-** ; 90h+2n width table (one word per character)
-** ; 90h+3n start of character definitions
-** ;
-** The individual character definitions consist of a variable number of words
-** describing the operations required to render a character. Each word
-** consists of an (x,y) coordinate pair and a two-bit opcode, encoded as shown
-** here:
-**
-** Byte 1 7 6 5 4 3 2 1 0 bit #
-** op1 <seven bit signed X coord>
-**
-** Byte 2 7 6 5 4 3 2 1 0 bit #
-** op2 <seven bit signed Y coord>
-**
-**
-** Opcodes
-**
-** op1=0 op2=0 End of character definition.
-** op1=1 op2=0 Move the pointer to (x,y)
-** op1=1 op2=1 Draw from current pointer to (x,y)
-*/
-
-
-
-/* The target file format is designed to be read by a cc65 compiled program
-** more easily. It should not be necessary to load the whole file into a
-** buffer to parse it, or seek within the file. Also using less memory if
-** possible would be fine. Therefore we use the following structure:
-**
-** Header portion:
-** .byte $54, $43, $48, $00 ; "TCH" version
-** .word <size of data portion>
-** Data portion:
-** .byte <top> ; Baseline to top
-** .byte <bottom> ; Baseline to bottom
-** .byte <height> ; Maximum char height
-** .byte <width>, ... ; $5F width bytes
-** .word <char definition offset>, ... ; $5F char def offsets
-** Character definitions:
-** .word <converted opcode>, ...
-** .byte $80
-**
-** The baseline of the character is assume to be at position zero. top and
-** bottom are both positive values. The former extends in positive, the other
-** in negative direction of the baseline. height contains the sum of top and
-** bottom and is stored here just for easier handling.
-**
-** The opcodes get converted for easier handling: END is marked by bit 7
-** set in the first byte. The second byte of this opcode is not needed.
-** Bit 7 of the second byte marks a MOVE (bit 7 = 0) or DRAW (bit 7 = 1).
-**
-** The number of characters is fixed to $20..$7E (space to tilde), so character
-** widths and offsets can be stored in fixed size preallocated tables. The
-** space for the character definitions is allocated on the heap, it's size
-** is stored in the header.
-**
-** Above structure allows a program to read the header portion of the file,
-** validate it, then read the remainder of the file into memory in one chunk.
-** The character definition offsets will then be converted into pointers by
-** adding the character definition base pointer to each.
-*/
-
-
-
-/*****************************************************************************/
-/* Data */
-/*****************************************************************************/
-
-
-
-static unsigned FilesProcessed = 0;
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-static void Usage (void)
-/* Print usage information and exit */
-{
- fprintf (stderr,
- "Usage: %s [options] file [options] [file]\n"
- "Short options:\n"
- " -h\t\t\tHelp (this text)\n"
- " -v\t\t\tBe more verbose\n"
- " -V\t\t\tPrint the version number and exit\n"
- "\n"
- "Long options:\n"
- " --help\t\tHelp (this text)\n"
- " --verbose\t\tBe more verbose\n"
- " --version\t\tPrint the version number and exit\n",
- ProgName);
-}
-
-
-
-static void OptHelp (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
-/* Print usage information and exit */
-{
- Usage ();
- exit (EXIT_SUCCESS);
-}
-
-
-
-static void OptVerbose (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
-/* Increase verbosity */
-{
- ++Verbosity;
-}
-
-
-
-static void OptVersion (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
-/* Print the assembler version */
-{
- fprintf (stderr,
- "%s V%s - (C) Copyright 2009, Ullrich von Bassewitz\n",
- ProgName, GetVersionAsString ());
-}
-
-
-
-static void ConvertChar (StrBuf* Data, const unsigned char* Buf, int Remaining)
-/* Convert data for one character. Original data is in Buf, converted data
-** will be placed in Data.
-*/
-{
- /* Convert all drawing vectors for this character */
- while (1) {
-
- unsigned Op;
-
- /* Check if we have enough data left */
- if (Remaining < 2) {
- Error ("End of file while parsing character definitions");
- }
-
- /* Get the next op word */
- Op = (Buf[0] + (Buf[1] << 8)) & 0x8080;
-
- /* Check the opcode */
- switch (Op) {
-
- case 0x0000:
- /* End */
- if (SB_IsEmpty (Data)) {
- /* No ops. We need to add an empty one */
- SB_AppendChar (Data, 0x00);
- SB_AppendChar (Data, 0x00);
- }
- /* Add an end marker to the last op in the buffer */
- SB_GetBuf (Data)[SB_GetLen (Data) - 2] |= 0x80;
- return;
-
- case 0x0080:
- /* Move */
- SB_AppendChar (Data, Buf[0] & 0x7F);
- SB_AppendChar (Data, Buf[1] & 0x7F);
- break;
-
- case 0x8000:
- /* Invalid opcode */
- Error ("Input file contains invalid opcode 0x8000");
- break;
-
- case 0x8080:
- /* Draw */
- SB_AppendChar (Data, Buf[0] & 0x7F);
- SB_AppendChar (Data, Buf[1] | 0x80);
- break;
- }
-
- /* Next Op */
- Buf += 2;
- Remaining -= 2;
- }
-}
-
-
-
-static void ConvertFile (const char* Input, const char* Output)
-/* Convert one vector font file */
-{
- /* The header of a BGI vector font file */
- static const unsigned char ChrHeader[] = {
- /* According to the Borland docs, the following should work, but it
- ** doesn't. Seems like there are fonts that work, but don't have the
- ** "BGI" string in the header. So we use just the PK\b\b mark as
- ** a header.
- **
- ** 0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20
- */
- 0x50, 0x4B, 0x08, 0x08
- };
-
- /* The header of a TGI vector font file */
- unsigned char TchHeader[] = {
- 0x54, 0x43, 0x48, 0x00, /* "TCH" version */
- 0x00, 0x00, /* size of char definitions */
- 0x00, /* Top */
- 0x00, /* Baseline */
- 0x00, /* Bottom */
- };
-
- long Size;
- unsigned char* Buf;
- unsigned char* MsgEnd;
- unsigned FirstChar;
- unsigned CharCount;
- unsigned LastChar;
- unsigned Char;
- unsigned Offs;
- const unsigned char* OffsetBuf;
- const unsigned char* WidthBuf;
- const unsigned char* VectorBuf;
- StrBuf Offsets = AUTO_STRBUF_INITIALIZER;
- StrBuf VectorData = AUTO_STRBUF_INITIALIZER;
-
-
- /* Try to open the file for reading */
- FILE* F = fopen (Input, "rb");
- if (F == 0) {
- Error ("Cannot open input file `%s': %s", Input, strerror (errno));
- }
-
- /* Seek to the end and determine the size */
- fseek (F, 0, SEEK_END);
- Size = ftell (F);
-
- /* Seek back to the start of the file */
- fseek (F, 0, SEEK_SET);
-
- /* Check if the size is reasonable */
- if (Size > 32*1024) {
- Error ("Input file `%s' is too large (max = 32k)", Input);
- } else if (Size < 0x100) {
- Error ("Input file `%s' is too small to be a vector font file", Input);
- }
-
- /* Allocate memory for the file */
- Buf = xmalloc ((size_t) Size);
-
- /* Read the file contents into the buffer */
- if (fread (Buf, 1, (size_t) Size, F) != (size_t) Size) {
- Error ("Error reading from input file `%s'", Input);
- }
-
- /* Close the file */
- (void) fclose (F);
-
- /* Verify the header */
- if (memcmp (Buf, ChrHeader, sizeof (ChrHeader)) != 0) {
- Error ("Invalid format for `%s': invalid header", Input);
- }
- MsgEnd = memchr (Buf + sizeof (ChrHeader), 0x1A, 0x80);
- if (MsgEnd == 0) {
- Error ("Invalid format for `%s': description not found", Input);
- }
- if (MsgEnd[1] != 0x80 || MsgEnd[2] != 0x00) {
- Error ("Invalid format for `%s': wrong header size", Input);
- }
-
- /* We expect the file to hold chars from 0x20 (space) to 0x7E (tilde) */
- FirstChar = Buf[0x84];
- CharCount = Buf[0x81] + (Buf[0x82] << 8);
- LastChar = FirstChar + CharCount - 1;
- if (FirstChar > 0x20 || LastChar < 0x7E) {
- Print (stderr, 1, "FirstChar = $%04X, CharCount = %u\n",
- FirstChar, CharCount);
- Error ("File `%s' doesn't contain the chars we need", Input);
- } else if (LastChar >= 0x100) {
- Error ("File `%s' contains too many character definitions", Input);
- }
-
- /* Print the copyright from the header */
- Print (stderr, 1, "%.*s\n", (int) (MsgEnd - Buf - 4), Buf+4);
-
- /* Get pointers to the width table, the offset table and the vector data
- ** table. The first two corrected for 0x20 as first entry.
- */
- OffsetBuf = Buf + 0x90 + ((0x20 - FirstChar) * 2);
- WidthBuf = Buf + 0x90 + (CharCount * 2) + (0x20 - FirstChar);
- VectorBuf = Buf + 0x90 + (CharCount * 3);
-
- /* Convert the characters */
- for (Char = 0x20; Char <= 0x7E; ++Char, OffsetBuf += 2) {
-
- int Remaining;
-
- /* Add the offset to the offset table */
- Offs = SB_GetLen (&VectorData);
- SB_AppendChar (&Offsets, Offs & 0xFF);
- SB_AppendChar (&Offsets, (Offs >> 8) & 0xFF);
-
- /* Get the offset of the vector data in the BGI data buffer */
- Offs = OffsetBuf[0] + (OffsetBuf[1] << 8);
-
- /* Calculate the remaining data in the buffer for this character */
- Remaining = Size - (Offs + (VectorBuf - Buf));
-
- /* Check if the offset is valid */
- if (Remaining <= 0) {
- Error ("Invalid data offset in input file `%s'", Input);
- }
-
- /* Convert the vector data and place it into the buffer */
- ConvertChar (&VectorData, VectorBuf + Offs, Remaining);
- }
-
- /* Complete the TCH header */
- Offs = 3 + 0x5F + 2*0x5F + SB_GetLen (&VectorData);
- TchHeader[4] = Offs & 0xFF;
- TchHeader[5] = (Offs >> 8) & 0xFF;
- TchHeader[6] = Buf[0x88];
- TchHeader[7] = (unsigned char) -(signed char)(Buf[0x8A]);
- TchHeader[8] = TchHeader[6] + TchHeader[7];
-
- /* The baseline must be zero, otherwise we cannot convert */
- if (Buf[0x89] != 0) {
- Error ("Baseline of font in `%s' is not zero", Input);
- }
-
- /* If the output file is NULL, use the name of the input file with ".tch"
- ** appended.
- */
- if (Output == 0) {
- Output = MakeFilename (Input, ".tch");
- }
-
- /* Open the output file */
- F = fopen (Output, "wb");
- if (F == 0) {
- Error ("Cannot open output file `%s': %s", Output, strerror (errno));
- }
-
- /* Write the header to the output file */
- if (fwrite (TchHeader, 1, sizeof (TchHeader), F) != sizeof (TchHeader)) {
- Error ("Error writing to `%s' (disk full?)", Output);
- }
-
- /* Write the width table to the output file */
- if (fwrite (WidthBuf, 1, 0x5F, F) != 0x5F) {
- Error ("Error writing to `%s' (disk full?)", Output);
- }
-
- /* Write the offsets to the output file */
- if (fwrite (SB_GetConstBuf (&Offsets), 1, 0x5F * 2, F) != 0x5F * 2) {
- Error ("Error writing to `%s' (disk full?)", Output);
- }
-
- /* Write the data to the output file */
- Offs = SB_GetLen (&VectorData);
- if (fwrite (SB_GetConstBuf (&VectorData), 1, Offs, F) != Offs) {
- Error ("Error writing to `%s' (disk full?)", Output);
- }
-
- /* Close the output file */
- if (fclose (F) != 0) {
- Error ("Error closing to `%s': %s", Output, strerror (errno));
- }
-
- /* Done */
-}
-
-
-
-int main (int argc, char* argv [])
-/* Assembler main program */
-{
- /* Program long options */
- static const LongOpt OptTab[] = {
- { "--help", 0, OptHelp },
- { "--verbose", 0, OptVerbose },
- { "--version", 0, OptVersion },
- };
-
- unsigned I;
-
- /* Initialize the cmdline module */
- InitCmdLine (&argc, &argv, "chrcvt");
-
- /* Check the parameters */
- I = 1;
- while (I < ArgCount) {
-
- /* Get the argument */
- const char* Arg = ArgVec[I];
-
- /* Check for an option */
- if (Arg [0] == '-') {
- switch (Arg [1]) {
-
- case '-':
- LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
- break;
-
- case 'h':
- OptHelp (Arg, 0);
- break;
-
- case 'v':
- OptVerbose (Arg, 0);
- break;
-
- case 'V':
- OptVersion (Arg, 0);
- break;
-
- default:
- UnknownOption (Arg);
- break;
-
- }
- } else {
- /* Filename. Dump it. */
- ConvertFile (Arg, 0);
- ++FilesProcessed;
- }
-
- /* Next argument */
- ++I;
- }
-
- /* Print a message if we did not process any files */
- if (FilesProcessed == 0) {
- fprintf (stderr, "%s: No input files\n", ProgName);
- }
-
- /* Success */
- return EXIT_SUCCESS;
-}
-
-
-
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>chrcvt65</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>$(SolutionDir)..\bin\</OutDir>
+ <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(SolutionDir)..\bin\</OutDir>
+ <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="chrcvt65\error.c" />
+ <ClCompile Include="chrcvt65\main.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="chrcvt65\error.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+/*****************************************************************************/
+/* */
+/* error.c */
+/* */
+/* Error handling for the chrcvt65 vector font converter */
+/* */
+/* */
+/* */
+/* (C) 1998-2009, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "error.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void Warning (const char* Format, ...)
+/* Print a warning message */
+{
+ va_list ap;
+ va_start (ap, Format);
+ fprintf (stderr, "Warning: ");
+ vfprintf (stderr, Format, ap);
+ putc ('\n', stderr);
+ va_end (ap);
+}
+
+
+
+void Error (const char* Format, ...)
+/* Print an error message and die */
+{
+ va_list ap;
+ va_start (ap, Format);
+ fprintf (stderr, "Error: ");
+ vfprintf (stderr, Format, ap);
+ putc ('\n', stderr);
+ va_end (ap);
+ exit (EXIT_FAILURE);
+}
+
+
+
+void Internal (const char* Format, ...)
+/* Print an internal error message and die */
+{
+ va_list ap;
+ va_start (ap, Format);
+ fprintf (stderr, "Internal error: ");
+ vfprintf (stderr, Format, ap);
+ putc ('\n', stderr);
+ va_end (ap);
+ exit (EXIT_FAILURE);
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* error.h */
+/* */
+/* Error handling for the chrcvt65 vector font converter */
+/* */
+/* */
+/* */
+/* (C) 1998-2009, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* 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 ERROR_H
+#define ERROR_H
+
+
+
+/* common */
+#include "attrib.h"
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void Warning (const char* Format, ...) attribute((format(printf,1,2)));
+/* Print a warning message */
+
+void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
+/* Print an error message and die */
+
+void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
+/* Print an internal error message and die */
+
+
+
+/* End of error.h */
+
+#endif
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* main.c */
+/* */
+/* Main program of the chrcvt65 vector font converter */
+/* */
+/* */
+/* */
+/* (C) 2000-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/* common */
+#include "cmdline.h"
+#include "fname.h"
+#include "print.h"
+#include "strbuf.h"
+#include "xmalloc.h"
+#include "version.h"
+
+/* chrcvt65 */
+#include "error.h"
+
+
+
+/*
+** The following is a corrected doc from the BGI font editor toolkit:
+**
+** BGI Stroke File Format
+**
+** The structure of Borland .CHR (stroke) files is as follows:
+**
+** ; offset 0h is a Borland header:
+** ;
+** HeaderSize equ 080h
+** DataSize equ (size of font file)
+** descr equ "Triplex font"
+** fname equ "TRIP"
+** MajorVersion equ 1
+** MinorVersion equ 0
+**
+** db 'PK',8,8
+** db 'BGI ',descr,' V'
+** db MajorVersion+'0'
+** db (MinorVersion / 10)+'0',(MinorVersion mod 10)+'0'
+** db ' - 19 October 1987',0DH,0AH
+** db 'Copyright (c) 1987 Borland International', 0dh,0ah
+** db 0,1ah ; null & ctrl-Z = end
+**
+** dw HeaderSize ; size of header
+** db fname ; font name
+** dw DataSize ; font file size
+** db MajorVersion,MinorVersion ; version #'s
+** db 1,0 ; minimal version #'s
+**
+** db (HeaderSize - $) DUP (0) ; pad out to header size
+**
+** At offset 80h starts data for the file:
+**
+** ; 80h '+' flags stroke file type
+** ; 81h-82h number chars in font file (n)
+** ; 83h undefined
+** ; 84h ASCII value of first char in file
+** ; 85h-86h offset to stroke definitions (8+3n)
+** ; 87h scan flag (normally 0)
+** ; 88h distance from origin to top of capital
+** ; 89h distance from origin to baseline
+** ; 8Ah distance from origin to bottom descender
+** ; 8Bh-8Fh undefined
+** ; 90h offsets to individual character definitions
+** ; 90h+2n width table (one word per character)
+** ; 90h+3n start of character definitions
+** ;
+** The individual character definitions consist of a variable number of words
+** describing the operations required to render a character. Each word
+** consists of an (x,y) coordinate pair and a two-bit opcode, encoded as shown
+** here:
+**
+** Byte 1 7 6 5 4 3 2 1 0 bit #
+** op1 <seven bit signed X coord>
+**
+** Byte 2 7 6 5 4 3 2 1 0 bit #
+** op2 <seven bit signed Y coord>
+**
+**
+** Opcodes
+**
+** op1=0 op2=0 End of character definition.
+** op1=1 op2=0 Move the pointer to (x,y)
+** op1=1 op2=1 Draw from current pointer to (x,y)
+*/
+
+
+
+/* The target file format is designed to be read by a cc65 compiled program
+** more easily. It should not be necessary to load the whole file into a
+** buffer to parse it, or seek within the file. Also using less memory if
+** possible would be fine. Therefore we use the following structure:
+**
+** Header portion:
+** .byte $54, $43, $48, $00 ; "TCH" version
+** .word <size of data portion>
+** Data portion:
+** .byte <top> ; Baseline to top
+** .byte <bottom> ; Baseline to bottom
+** .byte <height> ; Maximum char height
+** .byte <width>, ... ; $5F width bytes
+** .word <char definition offset>, ... ; $5F char def offsets
+** Character definitions:
+** .word <converted opcode>, ...
+** .byte $80
+**
+** The baseline of the character is assume to be at position zero. top and
+** bottom are both positive values. The former extends in positive, the other
+** in negative direction of the baseline. height contains the sum of top and
+** bottom and is stored here just for easier handling.
+**
+** The opcodes get converted for easier handling: END is marked by bit 7
+** set in the first byte. The second byte of this opcode is not needed.
+** Bit 7 of the second byte marks a MOVE (bit 7 = 0) or DRAW (bit 7 = 1).
+**
+** The number of characters is fixed to $20..$7E (space to tilde), so character
+** widths and offsets can be stored in fixed size preallocated tables. The
+** space for the character definitions is allocated on the heap, it's size
+** is stored in the header.
+**
+** Above structure allows a program to read the header portion of the file,
+** validate it, then read the remainder of the file into memory in one chunk.
+** The character definition offsets will then be converted into pointers by
+** adding the character definition base pointer to each.
+*/
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+static unsigned FilesProcessed = 0;
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+static void Usage (void)
+/* Print usage information and exit */
+{
+ fprintf (stderr,
+ "Usage: %s [options] file [options] [file]\n"
+ "Short options:\n"
+ " -h\t\t\tHelp (this text)\n"
+ " -v\t\t\tBe more verbose\n"
+ " -V\t\t\tPrint the version number and exit\n"
+ "\n"
+ "Long options:\n"
+ " --help\t\tHelp (this text)\n"
+ " --verbose\t\tBe more verbose\n"
+ " --version\t\tPrint the version number and exit\n",
+ ProgName);
+}
+
+
+
+static void OptHelp (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Print usage information and exit */
+{
+ Usage ();
+ exit (EXIT_SUCCESS);
+}
+
+
+
+static void OptVerbose (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Increase verbosity */
+{
+ ++Verbosity;
+}
+
+
+
+static void OptVersion (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Print the assembler version */
+{
+ fprintf (stderr,
+ "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
+}
+
+
+
+static void ConvertChar (StrBuf* Data, const unsigned char* Buf, int Remaining)
+/* Convert data for one character. Original data is in Buf, converted data
+** will be placed in Data.
+*/
+{
+ /* Convert all drawing vectors for this character */
+ while (1) {
+
+ unsigned Op;
+
+ /* Check if we have enough data left */
+ if (Remaining < 2) {
+ Error ("End of file while parsing character definitions");
+ }
+
+ /* Get the next op word */
+ Op = (Buf[0] + (Buf[1] << 8)) & 0x8080;
+
+ /* Check the opcode */
+ switch (Op) {
+
+ case 0x0000:
+ /* End */
+ if (SB_IsEmpty (Data)) {
+ /* No ops. We need to add an empty one */
+ SB_AppendChar (Data, 0x00);
+ SB_AppendChar (Data, 0x00);
+ }
+ /* Add an end marker to the last op in the buffer */
+ SB_GetBuf (Data)[SB_GetLen (Data) - 2] |= 0x80;
+ return;
+
+ case 0x0080:
+ /* Move */
+ SB_AppendChar (Data, Buf[0] & 0x7F);
+ SB_AppendChar (Data, Buf[1] & 0x7F);
+ break;
+
+ case 0x8000:
+ /* Invalid opcode */
+ Error ("Input file contains invalid opcode 0x8000");
+ break;
+
+ case 0x8080:
+ /* Draw */
+ SB_AppendChar (Data, Buf[0] & 0x7F);
+ SB_AppendChar (Data, Buf[1] | 0x80);
+ break;
+ }
+
+ /* Next Op */
+ Buf += 2;
+ Remaining -= 2;
+ }
+}
+
+
+
+static void ConvertFile (const char* Input, const char* Output)
+/* Convert one vector font file */
+{
+ /* The header of a BGI vector font file */
+ static const unsigned char ChrHeader[] = {
+ /* According to the Borland docs, the following should work, but it
+ ** doesn't. Seems like there are fonts that work, but don't have the
+ ** "BGI" string in the header. So we use just the PK\b\b mark as
+ ** a header.
+ **
+ ** 0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20
+ */
+ 0x50, 0x4B, 0x08, 0x08
+ };
+
+ /* The header of a TGI vector font file */
+ unsigned char TchHeader[] = {
+ 0x54, 0x43, 0x48, 0x00, /* "TCH" version */
+ 0x00, 0x00, /* size of char definitions */
+ 0x00, /* Top */
+ 0x00, /* Baseline */
+ 0x00, /* Bottom */
+ };
+
+ long Size;
+ unsigned char* Buf;
+ unsigned char* MsgEnd;
+ unsigned FirstChar;
+ unsigned CharCount;
+ unsigned LastChar;
+ unsigned Char;
+ unsigned Offs;
+ const unsigned char* OffsetBuf;
+ const unsigned char* WidthBuf;
+ const unsigned char* VectorBuf;
+ StrBuf Offsets = AUTO_STRBUF_INITIALIZER;
+ StrBuf VectorData = AUTO_STRBUF_INITIALIZER;
+
+
+ /* Try to open the file for reading */
+ FILE* F = fopen (Input, "rb");
+ if (F == 0) {
+ Error ("Cannot open input file `%s': %s", Input, strerror (errno));
+ }
+
+ /* Seek to the end and determine the size */
+ fseek (F, 0, SEEK_END);
+ Size = ftell (F);
+
+ /* Seek back to the start of the file */
+ fseek (F, 0, SEEK_SET);
+
+ /* Check if the size is reasonable */
+ if (Size > 32*1024) {
+ Error ("Input file `%s' is too large (max = 32k)", Input);
+ } else if (Size < 0x100) {
+ Error ("Input file `%s' is too small to be a vector font file", Input);
+ }
+
+ /* Allocate memory for the file */
+ Buf = xmalloc ((size_t) Size);
+
+ /* Read the file contents into the buffer */
+ if (fread (Buf, 1, (size_t) Size, F) != (size_t) Size) {
+ Error ("Error reading from input file `%s'", Input);
+ }
+
+ /* Close the file */
+ (void) fclose (F);
+
+ /* Verify the header */
+ if (memcmp (Buf, ChrHeader, sizeof (ChrHeader)) != 0) {
+ Error ("Invalid format for `%s': invalid header", Input);
+ }
+ MsgEnd = memchr (Buf + sizeof (ChrHeader), 0x1A, 0x80);
+ if (MsgEnd == 0) {
+ Error ("Invalid format for `%s': description not found", Input);
+ }
+ if (MsgEnd[1] != 0x80 || MsgEnd[2] != 0x00) {
+ Error ("Invalid format for `%s': wrong header size", Input);
+ }
+
+ /* We expect the file to hold chars from 0x20 (space) to 0x7E (tilde) */
+ FirstChar = Buf[0x84];
+ CharCount = Buf[0x81] + (Buf[0x82] << 8);
+ LastChar = FirstChar + CharCount - 1;
+ if (FirstChar > 0x20 || LastChar < 0x7E) {
+ Print (stderr, 1, "FirstChar = $%04X, CharCount = %u\n",
+ FirstChar, CharCount);
+ Error ("File `%s' doesn't contain the chars we need", Input);
+ } else if (LastChar >= 0x100) {
+ Error ("File `%s' contains too many character definitions", Input);
+ }
+
+ /* Print the copyright from the header */
+ Print (stderr, 1, "%.*s\n", (int) (MsgEnd - Buf - 4), Buf+4);
+
+ /* Get pointers to the width table, the offset table and the vector data
+ ** table. The first two corrected for 0x20 as first entry.
+ */
+ OffsetBuf = Buf + 0x90 + ((0x20 - FirstChar) * 2);
+ WidthBuf = Buf + 0x90 + (CharCount * 2) + (0x20 - FirstChar);
+ VectorBuf = Buf + 0x90 + (CharCount * 3);
+
+ /* Convert the characters */
+ for (Char = 0x20; Char <= 0x7E; ++Char, OffsetBuf += 2) {
+
+ int Remaining;
+
+ /* Add the offset to the offset table */
+ Offs = SB_GetLen (&VectorData);
+ SB_AppendChar (&Offsets, Offs & 0xFF);
+ SB_AppendChar (&Offsets, (Offs >> 8) & 0xFF);
+
+ /* Get the offset of the vector data in the BGI data buffer */
+ Offs = OffsetBuf[0] + (OffsetBuf[1] << 8);
+
+ /* Calculate the remaining data in the buffer for this character */
+ Remaining = Size - (Offs + (VectorBuf - Buf));
+
+ /* Check if the offset is valid */
+ if (Remaining <= 0) {
+ Error ("Invalid data offset in input file `%s'", Input);
+ }
+
+ /* Convert the vector data and place it into the buffer */
+ ConvertChar (&VectorData, VectorBuf + Offs, Remaining);
+ }
+
+ /* Complete the TCH header */
+ Offs = 3 + 0x5F + 2*0x5F + SB_GetLen (&VectorData);
+ TchHeader[4] = Offs & 0xFF;
+ TchHeader[5] = (Offs >> 8) & 0xFF;
+ TchHeader[6] = Buf[0x88];
+ TchHeader[7] = (unsigned char) -(signed char)(Buf[0x8A]);
+ TchHeader[8] = TchHeader[6] + TchHeader[7];
+
+ /* The baseline must be zero, otherwise we cannot convert */
+ if (Buf[0x89] != 0) {
+ Error ("Baseline of font in `%s' is not zero", Input);
+ }
+
+ /* If the output file is NULL, use the name of the input file with ".tch"
+ ** appended.
+ */
+ if (Output == 0) {
+ Output = MakeFilename (Input, ".tch");
+ }
+
+ /* Open the output file */
+ F = fopen (Output, "wb");
+ if (F == 0) {
+ Error ("Cannot open output file `%s': %s", Output, strerror (errno));
+ }
+
+ /* Write the header to the output file */
+ if (fwrite (TchHeader, 1, sizeof (TchHeader), F) != sizeof (TchHeader)) {
+ Error ("Error writing to `%s' (disk full?)", Output);
+ }
+
+ /* Write the width table to the output file */
+ if (fwrite (WidthBuf, 1, 0x5F, F) != 0x5F) {
+ Error ("Error writing to `%s' (disk full?)", Output);
+ }
+
+ /* Write the offsets to the output file */
+ if (fwrite (SB_GetConstBuf (&Offsets), 1, 0x5F * 2, F) != 0x5F * 2) {
+ Error ("Error writing to `%s' (disk full?)", Output);
+ }
+
+ /* Write the data to the output file */
+ Offs = SB_GetLen (&VectorData);
+ if (fwrite (SB_GetConstBuf (&VectorData), 1, Offs, F) != Offs) {
+ Error ("Error writing to `%s' (disk full?)", Output);
+ }
+
+ /* Close the output file */
+ if (fclose (F) != 0) {
+ Error ("Error closing to `%s': %s", Output, strerror (errno));
+ }
+
+ /* Done */
+}
+
+
+
+int main (int argc, char* argv [])
+/* Assembler main program */
+{
+ /* Program long options */
+ static const LongOpt OptTab[] = {
+ { "--help", 0, OptHelp },
+ { "--verbose", 0, OptVerbose },
+ { "--version", 0, OptVersion },
+ };
+
+ unsigned I;
+
+ /* Initialize the cmdline module */
+ InitCmdLine (&argc, &argv, "chrcvt65");
+
+ /* Check the parameters */
+ I = 1;
+ while (I < ArgCount) {
+
+ /* Get the argument */
+ const char* Arg = ArgVec[I];
+
+ /* Check for an option */
+ if (Arg [0] == '-') {
+ switch (Arg [1]) {
+
+ case '-':
+ LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
+ break;
+
+ case 'h':
+ OptHelp (Arg, 0);
+ break;
+
+ case 'v':
+ OptVerbose (Arg, 0);
+ break;
+
+ case 'V':
+ OptVersion (Arg, 0);
+ break;
+
+ default:
+ UnknownOption (Arg);
+ break;
+
+ }
+ } else {
+ /* Filename. Dump it. */
+ ConvertFile (Arg, 0);
+ ++FilesProcessed;
+ }
+
+ /* Next argument */
+ ++I;
+ }
+
+ /* Print a message if we did not process any files */
+ if (FilesProcessed == 0) {
+ fprintf (stderr, "%s: No input files\n", ProgName);
+ }
+
+ /* Success */
+ return EXIT_SUCCESS;
+}
+
+
+
#include "filetype.h"
#include "fname.h"
#include "mmodel.h"
+#include "searchpath.h"
#include "strbuf.h"
#include "target.h"
#include "version.h"
" --o65-model model\t\tOverride the o65 model\n"
" --obj file\t\t\tLink this object file\n"
" --obj-path path\t\tSpecify an object file search path\n"
+ " --print-target-path\t\tPrint the target file path\n"
" --register-space b\t\tSet space available for register variables\n"
" --register-vars\t\tEnable register variables\n"
" --rodata-name seg\t\tSet the name of the RODATA segment\n"
+static void OptPrintTargetPath (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Print the target file path */
+{
+ SearchPaths* TargetPath = NewSearchPath ();
+ AddSubSearchPathFromEnv (TargetPath, "CC65_HOME", "target");
+#if defined(CL65_TGT) && !defined(_WIN32)
+ AddSearchPath (TargetPath, STRINGIZE (CL65_TGT));
+#endif
+ AddSubSearchPathFromWinBin (TargetPath, "target");
+
+ printf ("%s\n", GetSearchPath (TargetPath, 0));
+ exit (EXIT_SUCCESS);
+}
+
+
+
static void OptRegisterSpace (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --register-space option */
{
const char* Arg attribute ((unused)))
/* Print version number */
{
- fprintf (stderr, "cl65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
{
/* Program long options */
static const LongOpt OptTab[] = {
- { "--add-source", 0, OptAddSource },
- { "--asm-args", 1, OptAsmArgs },
- { "--asm-define", 1, OptAsmDefine },
- { "--asm-include-dir", 1, OptAsmIncludeDir },
- { "--bin-include-dir", 1, OptBinIncludeDir },
- { "--bss-label", 1, OptBssLabel },
- { "--bss-name", 1, OptBssName },
- { "--cc-args", 1, OptCCArgs },
- { "--cfg-path", 1, OptCfgPath },
- { "--check-stack", 0, OptCheckStack },
- { "--code-label", 1, OptCodeLabel },
- { "--code-name", 1, OptCodeName },
- { "--codesize", 1, OptCodeSize },
- { "--config", 1, OptConfig },
- { "--cpu", 1, OptCPU },
- { "--create-dep", 1, OptCreateDep },
- { "--create-full-dep", 1, OptCreateFullDep },
- { "--data-label", 1, OptDataLabel },
- { "--data-name", 1, OptDataName },
- { "--debug", 0, OptDebug },
- { "--debug-info", 0, OptDebugInfo },
- { "--feature", 1, OptFeature },
- { "--force-import", 1, OptForceImport },
- { "--help", 0, OptHelp },
- { "--include-dir", 1, OptIncludeDir },
- { "--ld-args", 1, OptLdArgs },
- { "--lib", 1, OptLib },
- { "--lib-path", 1, OptLibPath },
- { "--list-targets", 0, OptListTargets },
- { "--listing", 1, OptListing },
- { "--list-bytes", 1, OptListBytes },
- { "--mapfile", 1, OptMapFile },
- { "--memory-model", 1, OptMemoryModel },
- { "--module", 0, OptModule },
- { "--module-id", 1, OptModuleId },
- { "--o65-model", 1, OptO65Model },
- { "--obj", 1, OptObj },
- { "--obj-path", 1, OptObjPath },
- { "--register-space", 1, OptRegisterSpace },
- { "--register-vars", 0, OptRegisterVars },
- { "--rodata-name", 1, OptRodataName },
- { "--signed-chars", 0, OptSignedChars },
- { "--standard", 1, OptStandard },
- { "--start-addr", 1, OptStartAddr },
- { "--static-locals", 0, OptStaticLocals },
- { "--target", 1, OptTarget },
- { "--verbose", 0, OptVerbose },
- { "--version", 0, OptVersion },
- { "--zeropage-label", 1, OptZeropageLabel },
- { "--zeropage-name", 1, OptZeropageName },
+ { "--add-source", 0, OptAddSource },
+ { "--asm-args", 1, OptAsmArgs },
+ { "--asm-define", 1, OptAsmDefine },
+ { "--asm-include-dir", 1, OptAsmIncludeDir },
+ { "--bin-include-dir", 1, OptBinIncludeDir },
+ { "--bss-label", 1, OptBssLabel },
+ { "--bss-name", 1, OptBssName },
+ { "--cc-args", 1, OptCCArgs },
+ { "--cfg-path", 1, OptCfgPath },
+ { "--check-stack", 0, OptCheckStack },
+ { "--code-label", 1, OptCodeLabel },
+ { "--code-name", 1, OptCodeName },
+ { "--codesize", 1, OptCodeSize },
+ { "--config", 1, OptConfig },
+ { "--cpu", 1, OptCPU },
+ { "--create-dep", 1, OptCreateDep },
+ { "--create-full-dep", 1, OptCreateFullDep },
+ { "--data-label", 1, OptDataLabel },
+ { "--data-name", 1, OptDataName },
+ { "--debug", 0, OptDebug },
+ { "--debug-info", 0, OptDebugInfo },
+ { "--feature", 1, OptFeature },
+ { "--force-import", 1, OptForceImport },
+ { "--help", 0, OptHelp },
+ { "--include-dir", 1, OptIncludeDir },
+ { "--ld-args", 1, OptLdArgs },
+ { "--lib", 1, OptLib },
+ { "--lib-path", 1, OptLibPath },
+ { "--list-targets", 0, OptListTargets },
+ { "--listing", 1, OptListing },
+ { "--list-bytes", 1, OptListBytes },
+ { "--mapfile", 1, OptMapFile },
+ { "--memory-model", 1, OptMemoryModel },
+ { "--module", 0, OptModule },
+ { "--module-id", 1, OptModuleId },
+ { "--o65-model", 1, OptO65Model },
+ { "--obj", 1, OptObj },
+ { "--obj-path", 1, OptObjPath },
+ { "--print-target-path", 0, OptPrintTargetPath},
+ { "--register-space", 1, OptRegisterSpace },
+ { "--register-vars", 0, OptRegisterVars },
+ { "--rodata-name", 1, OptRodataName },
+ { "--signed-chars", 0, OptSignedChars },
+ { "--standard", 1, OptStandard },
+ { "--start-addr", 1, OptStartAddr },
+ { "--static-locals", 0, OptStaticLocals },
+ { "--target", 1, OptTarget },
+ { "--verbose", 0, OptVerbose },
+ { "--version", 0, OptVersion },
+ { "--zeropage-label", 1, OptZeropageLabel },
+ { "--zeropage-name", 1, OptZeropageName },
};
char* CmdPath;
const char* Arg attribute ((unused)))
/* Print the assembler version */
{
- fprintf (stderr, "co65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
{
/* Insert the item at the end of the current list */
CollInsert (C, Item, C->Count);
-}
+}
#endif
void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex)
/* Move an item from one position in the collection to another. OldIndex
-** is the current position of the item, NewIndex is the new index after
+** is the current position of the item, NewIndex is the new index before
** the function has done it's work. Existing entries with indices NewIndex
-** and up are moved one position upwards.
+** and up might be moved one position upwards.
*/
{
- /* Get the item and remove it from the collection */
+ /* Get the item; and, remove it from the collection */
void* Item = CollAt (C, OldIndex);
+
CollDelete (C, OldIndex);
/* Correct NewIndex if needed */
- if (NewIndex >= OldIndex) {
+ if (NewIndex > OldIndex) {
/* Position has changed with removal */
--NewIndex;
}
- /* Now insert it at the new position */
+ /* Now, insert it at the new position */
CollInsert (C, Item, NewIndex);
}
void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex);
/* Move an item from one position in the collection to another. OldIndex
-** is the current position of the item, NewIndex is the new index after
+** is the current position of the item, NewIndex is the new index before
** the function has done it's work. Existing entries with indices NewIndex
-** and up are moved one position upwards.
+** and up might be moved one position upwards.
*/
void CollMoveMultiple (Collection* C, unsigned Start, unsigned Count, unsigned Target);
"sweet16",
"huc6280",
"m740",
+ "4510",
};
/* Tables with CPU instruction sets */
CPU_ISET_SWEET16,
CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_HUC6280,
CPU_ISET_6502 | CPU_ISET_M740,
+ CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_4510,
};
CPU_SWEET16,
CPU_HUC6280, /* Used in PC engine */
CPU_M740, /* Mitsubishi 740 series MCUs */
+ CPU_4510, /* CPU of C65 */
CPU_COUNT /* Number of different CPUs */
} cpu_t;
CPU_ISET_SWEET16 = 1 << CPU_SWEET16,
CPU_ISET_HUC6280 = 1 << CPU_HUC6280,
CPU_ISET_M740 = 1 << CPU_M740,
+ CPU_ISET_4510 = 1 << CPU_4510,
};
/* CPU used */
+char* GetSearchPath (SearchPaths* P, unsigned Index)
+/* Return the search path at the given index, if the index is valid, return an
+** empty string otherwise.
+*/
+{
+ if (Index < CollCount (P))
+ return CollAtUnchecked (P, Index);
+ return "";
+}
+
+
+
char* SearchFile (const SearchPaths* P, const char* File)
/* Search for a file in a list of directories. Return a pointer to a malloced
** area that contains the complete path, if found, return 0 otherwise.
void PopSearchPath (SearchPaths* P);
/* Remove a search path from the head of an existing search path list */
+char* GetSearchPath (SearchPaths* P, unsigned Index);
+/* Return the search path at the given index, if the index is valid, return an
+** empty string otherwise.
+*/
+
char* SearchFile (const SearchPaths* P, const char* File);
/* Search for a file in a list of directories. Return a pointer to a malloced
** area that contains the complete path, if found, return 0 otherwise.
};
/* Table that maps target names to ids. Sorted alphabetically for bsearch.
-** Allows mupltiple entries for one target id (target name aliases).
+** Allows multiple entries for one target id (target name aliases).
*/
static const TargetEntry TargetMap[] = {
{ "apple2", TGT_APPLE2 },
{ "apple2enh", TGT_APPLE2ENH },
{ "atari", TGT_ATARI },
+ { "atari2600", TGT_ATARI2600 },
{ "atari5200", TGT_ATARI5200 },
{ "atarixl", TGT_ATARIXL },
{ "atmos", TGT_ATMOS },
{ "c128", TGT_C128 },
{ "c16", TGT_C16 },
{ "c64", TGT_C64 },
+ { "c65", TGT_C65 },
{ "cbm510", TGT_CBM510 },
{ "cbm610", TGT_CBM610 },
{ "creativision", TGT_CREATIVISION},
{ "sim6502", TGT_SIM6502 },
{ "sim65c02", TGT_SIM65C02 },
{ "supervision", TGT_SUPERVISION },
- { "vc20", TGT_VIC20 },
{ "vic20", TGT_VIC20 },
};
#define MAP_ENTRY_COUNT (sizeof (TargetMap) / sizeof (TargetMap[0]))
{ "none", CPU_6502, BINFMT_BINARY, CTNone },
{ "module", CPU_6502, BINFMT_O65, CTNone },
{ "atari", CPU_6502, BINFMT_BINARY, CTAtari },
+ { "atari2600", CPU_6502, BINFMT_BINARY, CTNone },
{ "atari5200", CPU_6502, BINFMT_BINARY, CTAtari },
{ "atarixl", CPU_6502, BINFMT_BINARY, CTAtari },
{ "vic20", CPU_6502, BINFMT_BINARY, CTPET },
{ "geos-apple", CPU_65C02, BINFMT_BINARY, CTNone },
{ "geos-cbm", CPU_6502, BINFMT_BINARY, CTNone },
{ "lunix", CPU_6502, BINFMT_O65, CTNone },
- { "lynx", CPU_65C02, BINFMT_BINARY, CTNone },
+ { "atmos", CPU_6502, BINFMT_BINARY, CTNone },
{ "nes", CPU_6502, BINFMT_BINARY, CTNone },
+ { "supervision", CPU_65SC02, BINFMT_BINARY, CTNone },
+ { "lynx", CPU_65SC02, BINFMT_BINARY, CTNone },
{ "sim6502", CPU_6502, BINFMT_BINARY, CTNone },
{ "sim65c02", CPU_65C02, BINFMT_BINARY, CTNone },
{ "pce", CPU_HUC6280, BINFMT_BINARY, CTNone },
{ "gamate", CPU_6502, BINFMT_BINARY, CTNone },
{ "supervision", CPU_65SC02, BINFMT_BINARY, CTNone },
+ { "c65", CPU_4510, BINFMT_BINARY, CTPET },
};
/* Target system */
TGT_NONE,
TGT_MODULE,
TGT_ATARI,
+ TGT_ATARI2600,
TGT_ATARI5200,
TGT_ATARIXL,
TGT_VIC20,
TGT_PCENGINE,
TGT_GAMATE,
TGT_SUPERVISION,
+ TGT_C65,
TGT_COUNT /* Number of target systems */
} target_t;
void TgtTranslateSet (unsigned Index, unsigned char C)
/* Set the translation code for the given character */
{
- CHECK (Index > 0 && Index < sizeof (Tab));
+ CHECK (Index < sizeof (Tab));
Tab[Index] = C;
}
<ClCompile Include="da65\infofile.c" />
<ClCompile Include="da65\labels.c" />
<ClCompile Include="da65\main.c" />
+ <ClCompile Include="da65\opc4510.c" />
<ClCompile Include="da65\opc6502.c" />
<ClCompile Include="da65\opc6502x.c" />
<ClCompile Include="da65\opc65816.c" />
<ClInclude Include="da65\handler.h" />
<ClInclude Include="da65\infofile.h" />
<ClInclude Include="da65\labels.h" />
+ <ClInclude Include="da65\opc4510.h" />
<ClInclude Include="da65\opc6502.h" />
<ClInclude Include="da65\opc6502x.h" />
<ClInclude Include="da65\opc65816.h" />
#include <stdarg.h>
/* common */
+#include "xmalloc.h"
#include "xsprintf.h"
/* da65 */
+void OH_ImmediateWord (const OpcDesc* D)
+{
+ OneLine (D, "#$%04X", GetCodeWord (PC+1));
+}
+
+
+
void OH_Direct (const OpcDesc* D)
{
/* Get the operand */
+void OH_RelativeLong4510 (const OpcDesc* D attribute ((unused)))
+{
+ /* Get the operand */
+ signed short Offs = GetCodeWord (PC+1);
+
+ /* Calculate the target address */
+ unsigned Addr = (((int) PC+2) + Offs) & 0xFFFF;
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
+ /* Output the line */
+ OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
+}
+
+
+
void OH_DirectIndirect (const OpcDesc* D)
{
/* Get the operand */
+void OH_DirectIndirectZ (const OpcDesc* D)
+{
+ /* Get the operand */
+ unsigned Addr = GetCodeByte (PC+1);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
+ /* Output the line */
+ OneLine (D, "(%s),z", GetAddrArg (D->Flags, Addr));
+}
+
+
+
void OH_DirectXIndirect (const OpcDesc* D)
{
/* Get the operand */
void OH_BitBranch (const OpcDesc* D)
{
+ char* BranchLabel;
+
/* Get the operands */
unsigned char TestAddr = GetCodeByte (PC+1);
signed char BranchOffs = GetCodeByte (PC+2);
GenerateLabel (D->Flags, TestAddr);
GenerateLabel (flLabel, BranchAddr);
+ /* Make a copy of an operand, so that
+ ** the other operand can't overwrite it.
+ ** [GetAddrArg() uses a statically-stored buffer.]
+ */
+ BranchLabel = xstrdup (GetAddrArg (flLabel, BranchAddr));
+
/* Output the line */
- OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), GetAddrArg (flLabel, BranchAddr));
+ OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), BranchLabel);
+
+ xfree (BranchLabel);
}
void OH_StackRelativeIndirectY (const OpcDesc* D attribute ((unused)))
{
- Error ("Not implemented");
+ /* Output the line */
+ OneLine (D, "($%02X,s),y", GetCodeByte (PC+1));
+}
+
+
+
+void OH_StackRelativeIndirectY4510 (const OpcDesc* D attribute ((unused)))
+{
+ /* Output the line */
+ OneLine (D, "($%02X,sp),y", GetCodeByte (PC+1));
}
-void OH_BlockMove (const OpcDesc* D attribute ((unused)))
+void OH_BlockMove (const OpcDesc* D)
{
+ char* DstLabel;
+
/* Get source operand */
unsigned Src = GetCodeWord (PC+1);
/* Get destination operand */
GenerateLabel (D->Flags, Src);
GenerateLabel (D->Flags, Dst);
+ /* Make a copy of an operand, so that
+ ** the other operand can't overwrite it.
+ ** [GetAddrArg() uses a statically-stored buffer.]
+ */
+ DstLabel = xstrdup (GetAddrArg (D->Flags, Dst));
+
/* Output the line */
- OneLine (D, "%s%s,%s%s,#$%02X",
+ OneLine (D, "%s%s,%s%s,$%04X",
GetAbsOverride (D->Flags, Src), GetAddrArg (D->Flags, Src),
- GetAbsOverride (D->Flags, Dst), GetAddrArg (D->Flags, Dst),
+ GetAbsOverride (D->Flags, Dst), DstLabel,
GetCodeWord (PC+5));
+
+ xfree (DstLabel);
}
}
SeparatorLine ();
}
+
+
+
+void OH_JmpAbsoluteXIndirect (const OpcDesc* D)
+{
+ OH_AbsoluteXIndirect (D);
+ if (NewlineAfterJMP) {
+ LineFeed ();
+ }
+ SeparatorLine ();
+}
void OH_Accumulator (const OpcDesc*);
void OH_Implicit (const OpcDesc*);
void OH_Immediate (const OpcDesc*);
+void OH_ImmediateWord (const OpcDesc*);
void OH_Direct (const OpcDesc*);
void OH_DirectX (const OpcDesc*);
void OH_DirectY (const OpcDesc*);
void OH_AbsoluteLongX (const OpcDesc*);
void OH_Relative (const OpcDesc*);
void OH_RelativeLong (const OpcDesc*);
+void OH_RelativeLong4510 (const OpcDesc*);
void OH_DirectIndirect (const OpcDesc*);
void OH_DirectIndirectY (const OpcDesc*);
+void OH_DirectIndirectZ (const OpcDesc*);
void OH_DirectXIndirect (const OpcDesc*);
void OH_AbsoluteIndirect (const OpcDesc*);
void OH_StackRelative (const OpcDesc*);
void OH_DirectIndirectLongX (const OpcDesc*);
void OH_StackRelativeIndirectY (const OpcDesc*);
+void OH_StackRelativeIndirectY4510 (const OpcDesc*);
void OH_DirectIndirectLong (const OpcDesc*);
void OH_DirectIndirectLongY (const OpcDesc*);
void OH_BlockMove (const OpcDesc*);
void OH_AccumulatorBitBranch (const OpcDesc*);
void OH_JmpDirectIndirect (const OpcDesc* D);
void OH_SpecialPage (const OpcDesc*);
-
+
/* Handlers for special instructions */
void OH_Rts (const OpcDesc*);
void OH_JmpAbsolute (const OpcDesc*);
void OH_JmpAbsoluteIndirect (const OpcDesc* D);
+void OH_JmpAbsoluteXIndirect (const OpcDesc* D);
const char* Arg attribute ((unused)))
/* Print the disassembler version */
{
- fprintf (stderr, "da65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
--- /dev/null
+/*****************************************************************************/
+/* */
+/* opc4510.c */
+/* */
+/* 4510 opcode description table */
+/* */
+/* */
+/* */
+/* (C) 2003-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
+
+/* da65 */
+#include "handler.h"
+#include "opc4510.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Descriptions for all opcodes */
+const OpcDesc OpcTable_4510[256] = {
+ { "brk", 1, flNone, OH_Implicit }, /* $00 */
+ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */
+ { "cle", 1, flNone, OH_Implicit }, /* $02 */
+ { "see", 1, flNone, OH_Implicit }, /* $03 */
+ { "tsb", 2, flUseLabel, OH_Direct }, /* $04 */
+ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */
+ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */
+ { "rmb0", 2, flUseLabel, OH_Direct }, /* $07 */
+ { "php", 1, flNone, OH_Implicit }, /* $08 */
+ { "ora", 2, flNone, OH_Immediate }, /* $09 */
+ { "asl", 1, flNone, OH_Accumulator }, /* $0a */
+ { "tsy", 1, flNone, OH_Implicit }, /* $0b */
+ { "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */
+ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */
+ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */
+ { "bbr0", 3, flUseLabel, OH_BitBranch }, /* $0f */
+ { "bpl", 2, flLabel, OH_Relative }, /* $10 */
+ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */
+ { "ora", 2, flUseLabel, OH_DirectIndirectZ }, /* $12 */
+ { "lbpl", 3, flLabel, OH_RelativeLong4510 }, /* $13 */
+ { "trb", 2, flUseLabel, OH_Direct }, /* $14 */
+ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */
+ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */
+ { "rmb1", 2, flUseLabel, OH_Direct }, /* $17 */
+ { "clc", 1, flNone, OH_Implicit }, /* $18 */
+ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */
+ { "inc", 1, flNone, OH_Accumulator }, /* $1a */
+ { "inz", 1, flNone, OH_Implicit }, /* $1b */
+ { "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */
+ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */
+ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */
+ { "bbr1", 3, flUseLabel, OH_BitBranch }, /* $1f */
+ { "jsr", 3, flLabel, OH_Absolute }, /* $20 */
+ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */
+ { "jsr", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $22 */
+ { "jsr", 3, flLabel, OH_JmpAbsoluteXIndirect }, /* $23 */
+ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */
+ { "and", 2, flUseLabel, OH_Direct }, /* $25 */
+ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */
+ { "rmb2", 2, flUseLabel, OH_Direct }, /* $27 */
+ { "plp", 1, flNone, OH_Implicit }, /* $28 */
+ { "and", 2, flNone, OH_Immediate }, /* $29 */
+ { "rol", 1, flNone, OH_Accumulator }, /* $2a */
+ { "tys", 1, flNone, OH_Implicit }, /* $2b */
+ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */
+ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */
+ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */
+ { "bbr2", 3, flUseLabel, OH_BitBranch }, /* $2f */
+ { "bmi", 2, flLabel, OH_Relative }, /* $30 */
+ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */
+ { "and", 2, flUseLabel, OH_DirectIndirectZ }, /* $32 */
+ { "lbmi", 3, flLabel, OH_RelativeLong4510 }, /* $33 */
+ { "bit", 2, flUseLabel, OH_DirectX }, /* $34 */
+ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */
+ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */
+ { "rmb3", 2, flUseLabel, OH_Direct }, /* $37 */
+ { "sec", 1, flNone, OH_Implicit }, /* $38 */
+ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */
+ { "dec", 1, flNone, OH_Accumulator }, /* $3a */
+ { "dez", 1, flNone, OH_Implicit }, /* $3b */
+ { "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */
+ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */
+ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */
+ { "bbr3", 3, flUseLabel, OH_BitBranch }, /* $3f */
+ { "rti", 1, flNone, OH_Rts }, /* $40 */
+ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */
+ { "neg", 1, flNone, OH_Implicit }, /* $42 */
+ { "asr", 1, flNone, OH_Accumulator }, /* $43 */
+ { "asr", 2, flUseLabel, OH_Direct }, /* $44 */
+ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */
+ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */
+ { "rmb4", 2, flUseLabel, OH_Direct }, /* $47 */
+ { "pha", 1, flNone, OH_Implicit }, /* $48 */
+ { "eor", 2, flNone, OH_Immediate }, /* $49 */
+ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */
+ { "taz", 1, flNone, OH_Implicit }, /* $4b */
+ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */
+ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */
+ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */
+ { "bbr4", 3, flUseLabel, OH_BitBranch }, /* $4f */
+ { "bvc", 2, flLabel, OH_Relative }, /* $50 */
+ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */
+ { "eor", 2, flUseLabel, OH_DirectIndirectZ }, /* $52 */
+ { "lbvc", 3, flLabel, OH_RelativeLong4510 }, /* $53 */
+ { "asr", 2, flUseLabel, OH_DirectX }, /* $54 */
+ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */
+ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */
+ { "rmb5", 2, flUseLabel, OH_Direct }, /* $57 */
+ { "cli", 1, flNone, OH_Implicit }, /* $58 */
+ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */
+ { "phy", 1, flNone, OH_Implicit }, /* $5a */
+ { "tab", 1, flNone, OH_Implicit }, /* $5b */
+ { "map", 1, flNone, OH_Implicit }, /* $5c */
+ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */
+ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */
+ { "bbr5", 3, flUseLabel, OH_BitBranch }, /* $5f */
+ { "rts", 1, flNone, OH_Rts }, /* $60 */
+ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */
+ { "rtn", 2, flNone, OH_Immediate }, /* $62 */
+ { "bsr", 3, flLabel, OH_RelativeLong4510 }, /* $63 */
+ { "stz", 2, flUseLabel, OH_Direct }, /* $64 */
+ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */
+ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */
+ { "rmb6", 2, flUseLabel, OH_Direct, }, /* $67 */
+ { "pla", 1, flNone, OH_Implicit }, /* $68 */
+ { "adc", 2, flNone, OH_Immediate }, /* $69 */
+ { "ror", 1, flNone, OH_Accumulator }, /* $6a */
+ { "tza", 1, flNone, OH_Implicit }, /* $6b */
+ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */
+ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */
+ { "ror", 3, flUseLabel, OH_Absolute }, /* $6e */
+ { "bbr6", 3, flUseLabel, OH_BitBranch }, /* $6f */
+ { "bvs", 2, flLabel, OH_Relative }, /* $70 */
+ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */
+ { "adc", 2, flUseLabel, OH_DirectIndirectZ }, /* $72 */
+ { "lbvs", 3, flLabel, OH_RelativeLong4510 }, /* $73 */
+ { "stz", 2, flUseLabel, OH_DirectX }, /* $74 */
+ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */
+ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */
+ { "rmb7", 2, flUseLabel, OH_Direct }, /* $77 */
+ { "sei", 1, flNone, OH_Implicit }, /* $78 */
+ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */
+ { "ply", 1, flNone, OH_Implicit }, /* $7a */
+ { "tba", 1, flNone, OH_Implicit }, /* $7b */
+ { "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */
+ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */
+ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */
+ { "bbr7", 3, flUseLabel, OH_BitBranch }, /* $7f */
+ { "bra", 2, flLabel, OH_Relative }, /* $80 */
+ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */
+ { "sta", 2, flNone, OH_StackRelativeIndirectY4510}, /* $82 */
+ { "lbra", 3, flLabel, OH_RelativeLong4510 }, /* $83 */
+ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */
+ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */
+ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */
+ { "smb0", 2, flUseLabel, OH_Direct }, /* $87 */
+ { "dey", 1, flNone, OH_Implicit }, /* $88 */
+ { "bit", 2, flNone, OH_Immediate }, /* $89 */
+ { "txa", 1, flNone, OH_Implicit }, /* $8a */
+ { "sty", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $8b */
+ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */
+ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */
+ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */
+ { "bbs0", 3, flUseLabel, OH_BitBranch }, /* $8f */
+ { "bcc", 2, flLabel, OH_Relative }, /* $90 */
+ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */
+ { "sta", 2, flUseLabel, OH_DirectIndirectZ }, /* $92 */
+ { "lbcc", 3, flLabel, OH_RelativeLong4510 }, /* $93 */
+ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */
+ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */
+ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */
+ { "smb1", 2, flUseLabel, OH_Direct }, /* $97 */
+ { "tya", 1, flNone, OH_Implicit }, /* $98 */
+ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */
+ { "txs", 1, flNone, OH_Implicit }, /* $9a */
+ { "stx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $9b */
+ { "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */
+ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */
+ { "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */
+ { "bbs1", 3, flUseLabel, OH_BitBranch }, /* $9f */
+ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */
+ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */
+ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */
+ { "ldz", 2, flNone, OH_Immediate }, /* $a3 */
+ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */
+ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */
+ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */
+ { "smb2", 2, flUseLabel, OH_Direct }, /* $a7 */
+ { "tay", 1, flNone, OH_Implicit }, /* $a8 */
+ { "lda", 2, flNone, OH_Immediate }, /* $a9 */
+ { "tax", 1, flNone, OH_Implicit }, /* $aa */
+ { "ldz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ab */
+ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */
+ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */
+ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */
+ { "bbs2", 3, flUseLabel, OH_BitBranch }, /* $af */
+ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */
+ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */
+ { "lda", 2, flUseLabel, OH_DirectIndirectZ }, /* $b2 */
+ { "lbcs", 3, flLabel, OH_RelativeLong4510 }, /* $b3 */
+ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */
+ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */
+ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */
+ { "smb3", 2, flUseLabel, OH_Direct }, /* $b7 */
+ { "clv", 1, flNone, OH_Implicit }, /* $b8 */
+ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */
+ { "tsx", 1, flNone, OH_Implicit }, /* $ba */
+ { "ldz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bb */
+ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */
+ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */
+ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */
+ { "bbs3", 3, flUseLabel, OH_BitBranch }, /* $bf */
+ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */
+ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */
+ { "cpz", 2, flNone, OH_Immediate }, /* $c2 */
+ { "dew", 2, flUseLabel, OH_Direct }, /* $c3 */
+ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */
+ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */
+ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */
+ { "smb4", 2, flUseLabel, OH_Direct }, /* $c7 */
+ { "iny", 1, flNone, OH_Implicit }, /* $c8 */
+ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */
+ { "dex", 1, flNone, OH_Implicit }, /* $ca */
+ { "asw", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cb */
+ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */
+ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */
+ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */
+ { "bbs4", 3, flUseLabel, OH_BitBranch }, /* $cf */
+ { "bne", 2, flLabel, OH_Relative }, /* $d0 */
+ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */
+ { "cmp", 2, flUseLabel, OH_DirectIndirectZ }, /* $d2 */
+ { "lbne", 3, flLabel, OH_RelativeLong4510 }, /* $d3 */
+ { "cpz", 2, flUseLabel, OH_Direct }, /* $d4 */
+ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */
+ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */
+ { "smb5", 2, flUseLabel, OH_Direct }, /* $d7 */
+ { "cld", 1, flNone, OH_Implicit }, /* $d8 */
+ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */
+ { "phx", 1, flNone, OH_Implicit }, /* $da */
+ { "phz", 1, flNone, OH_Implicit }, /* $db */
+ { "cpz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $dc */
+ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */
+ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */
+ { "bbs5", 3, flUseLabel, OH_BitBranch }, /* $df */
+ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */
+ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */
+ { "lda", 2, flNone, OH_StackRelativeIndirectY4510}, /* $e2 */
+ { "inw", 2, flUseLabel, OH_Direct }, /* $e3 */
+ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */
+ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */
+ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */
+ { "smb6", 2, flUseLabel, OH_Direct }, /* $e7 */
+ { "inx", 1, flNone, OH_Implicit }, /* $e8 */
+ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */
+ { "eom", 1, flNone, OH_Implicit }, /* $ea */
+ { "row", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $eb */
+ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */
+ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */
+ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */
+ { "bbs6", 3, flUseLabel, OH_BitBranch }, /* $ef */
+ { "beq", 2, flLabel, OH_Relative }, /* $f0 */
+ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */
+ { "sbc", 2, flUseLabel, OH_DirectIndirectZ }, /* $f2 */
+ { "lbeq", 3, flLabel, OH_RelativeLong4510 }, /* $f3 */
+ { "phw", 3, flNone, OH_ImmediateWord }, /* $f4 */
+ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */
+ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */
+ { "smb7", 2, flUseLabel, OH_Direct }, /* $f7 */
+ { "sed", 1, flNone, OH_Implicit }, /* $f8 */
+ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */
+ { "plx", 1, flNone, OH_Implicit }, /* $fa */
+ { "plz", 1, flNone, OH_Implicit }, /* $fb */
+ { "phw", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $fc */
+ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */
+ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */
+ { "bbs7", 3, flUseLabel, OH_BitBranch }, /* $ff */
+};
--- /dev/null
+/*****************************************************************************/
+/* */
+/* opc4510.h */
+/* */
+/* 4510 opcode description table */
+/* */
+/* */
+/* */
+/* (C) 2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
+/* */
+/* */
+/* 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 OPC4510_H
+#define OPC4510_H
+
+
+
+#include "opcdesc.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Descriptions for all opcodes */
+extern const OpcDesc OpcTable_4510[256];
+
+
+
+/* End of opc4510.h */
+
+#endif
{ "iny", 1, flNone, OH_Implicit }, /* $c8 */
{ "cmp", 2, flNone, OH_Immediate }, /* $c9 */
{ "dex", 1, flNone, OH_Implicit }, /* $ca */
- { "", 1, flIllegal, OH_Illegal, }, /* $cb */
+ { "wai", 1, flNone, OH_Implicit }, /* $cb */
{ "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */
{ "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */
{ "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */
{ "cld", 1, flNone, OH_Implicit }, /* $d8 */
{ "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */
{ "phx", 1, flNone, OH_Implicit }, /* $da */
- { "", 1, flIllegal, OH_Illegal, }, /* $db */
+ { "stp", 1, flNone, OH_Implicit }, /* $db */
{ "", 1, flIllegal, OH_Illegal, }, /* $dc */
{ "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */
{ "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */
{ "tsb", 2, flUseLabel, OH_Direct }, /* $04 */
{ "ora", 2, flUseLabel, OH_Direct }, /* $05 */
{ "asl", 2, flUseLabel, OH_Direct }, /* $06 */
- { "rmb0", 1, flUseLabel, OH_Direct, }, /* $07 */
+ { "rmb0", 2, flUseLabel, OH_Direct, }, /* $07 */
{ "php", 1, flNone, OH_Implicit }, /* $08 */
{ "ora", 2, flNone, OH_Immediate }, /* $09 */
{ "asl", 1, flNone, OH_Accumulator }, /* $0a */
{ "trb", 2, flUseLabel, OH_Direct }, /* $14 */
{ "ora", 2, flUseLabel, OH_DirectX }, /* $15 */
{ "asl", 2, flUseLabel, OH_DirectX }, /* $16 */
- { "rmb1", 1, flUseLabel, OH_Direct, }, /* $17 */
+ { "rmb1", 2, flUseLabel, OH_Direct, }, /* $17 */
{ "clc", 1, flNone, OH_Implicit }, /* $18 */
{ "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */
{ "inc", 1, flNone, OH_Accumulator }, /* $1a */
{ "bit", 2, flUseLabel, OH_Direct }, /* $24 */
{ "and", 2, flUseLabel, OH_Direct }, /* $25 */
{ "rol", 2, flUseLabel, OH_Direct }, /* $26 */
- { "rmb2", 1, flUseLabel, OH_Direct, }, /* $27 */
+ { "rmb2", 2, flUseLabel, OH_Direct, }, /* $27 */
{ "plp", 1, flNone, OH_Implicit }, /* $28 */
{ "and", 2, flNone, OH_Immediate }, /* $29 */
{ "rol", 1, flNone, OH_Accumulator }, /* $2a */
{ "bit", 2, flUseLabel, OH_DirectX }, /* $34 */
{ "and", 2, flUseLabel, OH_DirectX }, /* $35 */
{ "rol", 2, flUseLabel, OH_DirectX }, /* $36 */
- { "rmb3", 1, flUseLabel, OH_Direct, }, /* $37 */
+ { "rmb3", 2, flUseLabel, OH_Direct, }, /* $37 */
{ "sec", 1, flNone, OH_Implicit }, /* $38 */
{ "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */
{ "dec", 1, flNone, OH_Accumulator }, /* $3a */
{ "rti", 1, flNone, OH_Rts }, /* $40 */
{ "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */
{ "say", 1, flNone, OH_Implicit, }, /* $42 */
- { "tmai", 2, flNone, OH_Immediate, }, /* $43 */
+ { "tma", 2, flNone, OH_Immediate, }, /* $43 */
{ "bsr", 2, flLabel, OH_Relative, }, /* $44 */
{ "eor", 2, flUseLabel, OH_Direct }, /* $45 */
{ "lsr", 2, flUseLabel, OH_Direct }, /* $46 */
- { "rmb4", 1, flUseLabel, OH_Direct, }, /* $47 */
+ { "rmb4", 2, flUseLabel, OH_Direct, }, /* $47 */
{ "pha", 1, flNone, OH_Implicit }, /* $48 */
{ "eor", 2, flNone, OH_Immediate }, /* $49 */
{ "lsr", 1, flNone, OH_Accumulator }, /* $4a */
{ "bvc", 2, flLabel, OH_Relative }, /* $50 */
{ "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */
{ "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */
- { "tami", 2, flNone, OH_Immediate, }, /* $53 */
+ { "tam", 2, flNone, OH_Immediate, }, /* $53 */
{ "csl", 1, flNone, OH_Implicit, }, /* $54 */
{ "eor", 2, flUseLabel, OH_DirectX }, /* $55 */
{ "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */
- { "rmb5", 1, flUseLabel, OH_Direct, }, /* $57 */
+ { "rmb5", 2, flUseLabel, OH_Direct, }, /* $57 */
{ "cli", 1, flNone, OH_Implicit }, /* $58 */
{ "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */
{ "phy", 1, flNone, OH_Implicit }, /* $5a */
{ "stz", 2, flUseLabel, OH_Direct }, /* $64 */
{ "adc", 2, flUseLabel, OH_Direct }, /* $65 */
{ "ror", 2, flUseLabel, OH_Direct }, /* $66 */
- { "rmb6", 1, flUseLabel, OH_Direct, }, /* $67 */
+ { "rmb6", 2, flUseLabel, OH_Direct, }, /* $67 */
{ "pla", 1, flNone, OH_Implicit }, /* $68 */
{ "adc", 2, flNone, OH_Immediate }, /* $69 */
{ "ror", 1, flNone, OH_Accumulator }, /* $6a */
{ "stz", 2, flUseLabel, OH_DirectX }, /* $74 */
{ "adc", 2, flUseLabel, OH_DirectX }, /* $75 */
{ "ror", 2, flUseLabel, OH_DirectX }, /* $76 */
- { "rmb7", 1, flUseLabel, OH_Direct, }, /* $77 */
+ { "rmb7", 2, flUseLabel, OH_Direct, }, /* $77 */
{ "sei", 1, flNone, OH_Implicit }, /* $78 */
{ "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */
{ "ply", 1, flNone, OH_Implicit }, /* $7a */
{ "", 1, flIllegal, OH_Illegal, }, /* $7b */
- { "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */
+ { "jmp", 3, flLabel, OH_JmpAbsoluteXIndirect }, /* $7c */
{ "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */
{ "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */
{ "bbr7", 3, flUseLabel, OH_BitBranch }, /* $7f */
{ "sty", 2, flUseLabel, OH_Direct }, /* $84 */
{ "sta", 2, flUseLabel, OH_Direct }, /* $85 */
{ "stx", 2, flUseLabel, OH_Direct }, /* $86 */
- { "smb0", 1, flUseLabel, OH_Direct, }, /* $87 */
+ { "smb0", 2, flUseLabel, OH_Direct, }, /* $87 */
{ "dey", 1, flNone, OH_Implicit }, /* $88 */
{ "bit", 2, flNone, OH_Immediate }, /* $89 */
{ "txa", 1, flNone, OH_Implicit }, /* $8a */
{ "sty", 2, flUseLabel, OH_DirectX }, /* $94 */
{ "sta", 2, flUseLabel, OH_DirectX }, /* $95 */
{ "stx", 2, flUseLabel, OH_DirectY }, /* $96 */
- { "smb1", 1, flUseLabel, OH_Direct, }, /* $97 */
+ { "smb1", 2, flUseLabel, OH_Direct, }, /* $97 */
{ "tya", 1, flNone, OH_Implicit }, /* $98 */
{ "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */
{ "txs", 1, flNone, OH_Implicit }, /* $9a */
{ "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */
{ "lda", 2, flUseLabel, OH_Direct }, /* $a5 */
{ "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */
- { "smb2", 1, flUseLabel, OH_Direct, }, /* $a7 */
+ { "smb2", 2, flUseLabel, OH_Direct, }, /* $a7 */
{ "tay", 1, flNone, OH_Implicit }, /* $a8 */
{ "lda", 2, flNone, OH_Immediate }, /* $a9 */
{ "tax", 1, flNone, OH_Implicit }, /* $aa */
{ "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */
{ "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */
{ "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */
- { "smb3", 1, flUseLabel, OH_Direct, }, /* $b7 */
+ { "smb3", 2, flUseLabel, OH_Direct, }, /* $b7 */
{ "clv", 1, flNone, OH_Implicit }, /* $b8 */
{ "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */
{ "tsx", 1, flNone, OH_Implicit }, /* $ba */
{ "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */
{ "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */
{ "dec", 2, flUseLabel, OH_Direct }, /* $c6 */
- { "smb4", 1, flUseLabel, OH_Direct, }, /* $c7 */
+ { "smb4", 2, flUseLabel, OH_Direct, }, /* $c7 */
{ "iny", 1, flNone, OH_Implicit }, /* $c8 */
{ "cmp", 2, flNone, OH_Immediate }, /* $c9 */
{ "dex", 1, flNone, OH_Implicit }, /* $ca */
{ "csh", 1, flNone, OH_Implicit, }, /* $d4 */
{ "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */
{ "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */
- { "smb5", 1, flUseLabel, OH_Direct, }, /* $d7 */
+ { "smb5", 2, flUseLabel, OH_Direct, }, /* $d7 */
{ "cld", 1, flNone, OH_Implicit }, /* $d8 */
{ "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */
{ "phx", 1, flNone, OH_Implicit }, /* $da */
{ "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */
{ "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */
{ "inc", 2, flUseLabel, OH_Direct }, /* $e6 */
- { "smb6", 1, flUseLabel, OH_Direct, }, /* $e7 */
+ { "smb6", 2, flUseLabel, OH_Direct, }, /* $e7 */
{ "inx", 1, flNone, OH_Implicit }, /* $e8 */
{ "sbc", 2, flNone, OH_Immediate }, /* $e9 */
{ "nop", 1, flNone, OH_Implicit }, /* $ea */
{ "set", 1, flNone, OH_Implicit, }, /* $f4 */
{ "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */
{ "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */
- { "smb7", 1, flUseLabel, OH_Direct, }, /* $f7 */
+ { "smb7", 2, flUseLabel, OH_Direct, }, /* $f7 */
{ "sed", 1, flNone, OH_Implicit }, /* $f8 */
{ "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */
{ "plx", 1, flNone, OH_Implicit }, /* $fa */
/* da65 */
#include "error.h"
+#include "opc4510.h"
#include "opc6502.h"
#include "opc6502x.h"
#include "opc65816.h"
case CPU_65C02: OpcTable = OpcTable_65C02; break;
case CPU_HUC6280: OpcTable = OpcTable_HuC6280; break;
case CPU_M740: OpcTable = OpcTable_M740; break;
+ case CPU_4510: OpcTable = OpcTable_4510; break;
default: Error ("Unsupported CPU");
}
}
const char* Arg attribute ((unused)))
/* Print the program version */
{
- fprintf (stderr, "grc65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
PrintNumVal ("Address", Addr);
PrintNumVal ("FileOffs", (unsigned long) ftell (D->F));
- /* Check if the alignment for the segment from the linker config is
- ** a multiple for that of the segment.
- */
- if ((S->RunAlignment % S->Seg->Alignment) != 0) {
- /* Segment requires another alignment than configured
- ** in the linker.
- */
- Warning ("Segment `%s' is not aligned properly. Resulting "
- "executable may not be functional.",
- GetString (S->Name));
- }
-
/* If this is the run memory area, we must apply run alignment. If
** this is not the run memory area but the load memory area (which
** means that both are different), we must apply load alignment.
/* This is the run (and maybe load) memory area. Handle
** alignment and explict start address and offset.
*/
+
+ /* Check if the alignment for the segment from the linker
+ ** config. is a multiple for that of the segment.
+ */
+ if ((S->RunAlignment % S->Seg->Alignment) != 0) {
+ /* Segment requires another alignment than configured
+ ** in the linker.
+ */
+ CfgWarning (GetSourcePos (S->LI),
+ "Segment `%s' isn't aligned properly; the"
+ " resulting executable might not be functional.",
+ GetString (S->Name));
+ }
+
if (S->Flags & SF_ALIGN) {
/* Align the address */
unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment);
*/
if (M->FillLevel == 0 && NewAddr > Addr) {
CfgWarning (GetSourcePos (S->LI),
- "First segment in memory area `%s' does "
- "already need fill bytes for alignment",
+ "The first segment in memory area `%s' "
+ "needs fill bytes for alignment.",
GetString (M->Name));
}
const char* Arg attribute ((unused)))
/* Print the assembler version */
{
- fprintf (stderr, "ld65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
}
/* Not found or no identifier */
- CfgError (&CfgErrorPos, "%s expected", Name);
+ CfgError (&CfgErrorPos, "%s expected, got '%s'", Name, SB_GetConstBuf(&CfgSVal));
}
/* Print the assembler version */
{
fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
/* IRQ request active */
static unsigned HaveIRQRequest;
+/* flag to print cycles at program termination */
+int PrintCycles;
/*****************************************************************************/
unsigned long GetCycles (void);
/* Return the total number of clock cycles executed */
+extern int PrintCycles;
+/* flag to print cycles at program termination */
/* End of 6502.h */
const char* ProgramFile;
/* exit simulator after MaxCycles Cycles */
-unsigned long MaxCycles = 0;
+unsigned long MaxCycles;
/*****************************************************************************/
/* Code */
printf ("Usage: %s [options] file [arguments]\n"
"Short options:\n"
" -h\t\t\tHelp (this text)\n"
+ " -c\t\t\tPrint amount of executed CPU cycles\n"
" -v\t\t\tIncrease verbosity\n"
" -V\t\t\tPrint the simulator version number\n"
" -x <num>\t\tExit simulator after <num> cycles\n"
"\n"
"Long options:\n"
" --help\t\tHelp (this text)\n"
+ " --cycles\t\tPrint amount of executed CPU cycles\n"
" --verbose\t\tIncrease verbosity\n"
" --version\t\tPrint the simulator version number\n",
ProgName);
+static void OptCycles (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Set flag to print amount of cycles at the end */
+{
+ PrintCycles = 1;
+}
+
+
+
static void OptVersion (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Print the simulator version */
{
- fprintf (stderr, "sim65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
static void OptQuitXIns (const char* Opt attribute ((unused)),
/* Program long options */
static const LongOpt OptTab[] = {
{ "--help", 0, OptHelp },
+ { "--cycles", 0, OptCycles },
{ "--verbose", 0, OptVerbose },
{ "--version", 0, OptVersion },
};
OptHelp (Arg, 0);
break;
+ case 'c':
+ OptCycles (Arg, 0);
+ break;
+
case 'v':
OptVerbose (Arg, 0);
break;
static void PVExit (CPURegs* Regs)
{
Print (stderr, 1, "PVExit ($%02X)\n", Regs->AC);
+ if (PrintCycles) {
+ Print (stdout, 0, "%lu cycles\n", GetCycles ());
+ }
exit (Regs->AC);
}
"\n"
"Long options:\n"
" --convert-to fmt[,attrlist]\tConvert into target format\n"
+ " --dump-palette\t\tDump palette as table\n"
" --help\t\t\tHelp (this text)\n"
" --list-conversions\t\tList all possible conversions\n"
" --pop\t\t\t\tRestore the original loaded image\n"
static void OptVerbose (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
-/* Increase versbosity */
+/* Increase verbosity */
{
++Verbosity;
}
/* Print the assembler version */
{
fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
++I;
}
+ /* Do we have an input file? */
+ if (I == 1) {
+ Error ("No input file");
+ }
+
/* Cleanup data */
SetWorkBitmap (C);
FreeBitmap (B);
ifdef CMD_EXE
EXE := .exe
- DEL = -del /f $(subst /,\,$1)
MKDIR = mkdir $(subst /,\,$1)
RMDIR = -rmdir /s /q $(subst /,\,$1)
else
EXE :=
- DEL = $(RM) $1
MKDIR = mkdir $1
RMDIR = $(RM) -r $1
endif
CC := gcc
-.PHONY: all dotests continue mostly-clean clean
+.PHONY: all dotests continue mostlyclean clean
all: dotests
.NOTPARALLEL:
-dotests: mostly-clean continue
+dotests: mostlyclean continue
continue: $(WORKDIR)/bdiff$(EXE)
+ @$(MAKE) -C assembler all
+ @$(MAKE) -C disassembler all
@$(MAKE) -C val all
@$(MAKE) -C ref all
@$(MAKE) -C err all
@$(MAKE) -C misc all
-mostly-clean:
+mostlyclean:
@$(MAKE) -C val clean
@$(MAKE) -C ref clean
@$(MAKE) -C err clean
@$(MAKE) -C misc clean
-clean: mostly-clean
- @$(call DEL,$(WORKDIR)/bdiff$(EXE))
+clean: mostlyclean
@$(call RMDIR,$(WORKDIR))
--- /dev/null
+*.o
+*.bin
+*.lst
--- /dev/null
+.setcpu "4510"
+
+ brk
+ ora ($05,x)
+ cle
+ see
+ tsb $02
+ ora $02
+ asl $02
+ rmb0 $02
+ php
+ ora #$01
+ asl
+ tsy
+ tsb $1234
+ ora $1234
+ asl $1234
+ bbr0 $02,*+$34
+
+ bpl *+$32
+ ora ($06),y
+ ora ($07),z
+ lbpl *+$3133 ; bpl *+$3133
+ trb $02
+ ora $03,x
+ asl $03,x
+ rmb1 $02
+ clc
+ ora $1456,y
+ inc
+ inz
+ trb $1234
+ ora $1345,x
+ asl $1345,x
+ bbr1 $02,*+$34
+
+ jsr $1234
+ and ($05,x)
+ jsr ($2345)
+ jsr ($2456,x)
+ bit $02
+ and $02
+ rol $02
+ rmb2 $02
+ plp
+ and #$01
+ rol
+ tys
+ bit $1234
+ and $1234
+ rol $1234
+ bbr2 $02,*+$34
+
+ bmi *+$32
+ and ($06),y
+ and ($07),z
+ lbmi *+$3133 ; bmi *+$3133
+ bit $03,x
+ and $03,x
+ rol $03,x
+ rmb3 $02
+ sec
+ and $1456,y
+ dec
+ dez
+ bit $1345,x
+ and $1345,x
+ rol $1345,x
+ bbr3 $02,*+$34
+
+ rti
+ eor ($05,x)
+ neg
+ asr
+ asr $02
+ eor $02
+ lsr $02
+ rmb4 $02
+ pha
+ eor #$01
+ lsr
+ taz
+ jmp $1234
+ eor $1234
+ lsr $1234
+ bbr4 $02,*+$34
+
+ bvc *+$32
+ eor ($06),y
+ eor ($07),z
+ lbvc *+$3133 ; bvc *+$3133
+ asr $03,x
+ eor $03,x
+ lsr $03,x
+ rmb5 $02
+ cli
+ eor $1456,y
+ phy
+ tab
+ map
+ eor $1345,x
+ lsr $1345,x
+ bbr5 $02,*+$34
+
+ rts
+ adc ($05,x)
+ rtn #$09
+ bsr *+$3133
+ stz $02
+ adc $02
+ ror $02
+ rmb6 $02
+ pla
+ adc #$01
+ ror
+ tza
+ jmp ($2345)
+ adc $1234
+ ror $1234
+ bbr6 $02,*+$34
+
+ bvs *+$32
+ adc ($06),y
+ adc ($07),z
+ lbvs *+$3133 ; bvs *+$3133
+ stz $03,x
+ adc $03,x
+ ror $03,x
+ rmb7 $02
+ sei
+ adc $1456,y
+ ply
+ tba
+ jmp ($2456,x)
+ adc $1345,x
+ ror $1345,x
+ bbr7 $02,*+$34
+
+ bra *+$32
+ sta ($05,x)
+ sta ($0f,s),y
+ sta ($0f,sp),y
+ lbra *+$3133 ; bra *+$3133
+ sty $02
+ sta $02
+ stx $02
+ smb0 $02
+ dey
+ bit #$01
+ txa
+ sty $1345,x
+ sty $1234
+ sta $1234
+ stx $1234
+ bbs0 $02,*+$34
+
+ bcc *+$32
+ sta ($06),y
+ sta ($07),z
+ lbcc *+$3133 ; bcc *+$3133
+ sty $03,x
+ sta $03,x
+ stx $04,y
+ smb1 $02
+ tya
+ sta $1456,y
+ txs
+ stx $1456,y
+ stz $1234
+ sta $1345,x
+ stz $1345,x
+ bbs1 $02,*+$34
+
+ ldy #$01
+ lda ($05,x)
+ ldx #$01
+ ldz #$01
+ ldy $02
+ lda $02
+ ldx $02
+ smb2 $02
+ tay
+ lda #$01
+ tax
+ ldz $1234
+ ldy $1234
+ lda $1234
+ ldx $1234
+ bbs2 $02,*+$34
+
+ bcs *+$32
+ lda ($06),y
+ lda ($07),z
+ lbcs *+$3133 ; bcs *+$3133
+ ldy $03,x
+ lda $03,x
+ ldx $04,y
+ smb3 $02
+ clv
+ lda $1456,y
+ tsx
+ ldz $1345,x
+ ldy $1345,x
+ lda $1345,x
+ ldx $1456,y
+ bbs3 $02,*+$34
+
+ cpy #$01
+ cmp ($05,x)
+ cpz #$01
+ dew $02
+ cpy $02
+ cmp $02
+ dec $02
+ smb4 $02
+ iny
+ cmp #$01
+ dex
+ asw $1234
+ cpy $1234
+ cmp $1234
+ dec $1234
+ bbs4 $02,*+$34
+
+ bne *+$32
+ cmp ($06),y
+ cmp ($07),z
+ lbne *+$3133 ; bne *+$3133
+ cpz $02
+ cmp $03,x
+ dec $03,x
+ smb5 $02
+ cld
+ cmp $1456,y
+ phx
+ phz
+ cpz $1234
+ cmp $1345,x
+ dec $1345,x
+ bbs5 $02,*+$34
+
+ cpx #$01
+ sbc ($05,x)
+ lda ($0f,s),y
+ lda ($0f,sp),y
+ inw $02
+ cpx $02
+ sbc $02
+ inc $02
+ smb6 $02
+ inx
+ sbc #$01
+ eom
+ nop
+ row $1234
+ cpx $1234
+ sbc $1234
+ inc $1234
+ bbs6 $02,*+$34
+
+ beq *+$32
+ sbc ($06),y
+ sbc ($07),z
+ lbeq *+$3133 ; beq *+$3133
+ phd #$089a
+ phw #$089a
+ sbc $03,x
+ inc $03,x
+ smb7 $02
+ sed
+ sbc $1456,y
+ plx
+ plz
+ phd $1234
+ phw $1234
+ sbc $1345,x
+ inc $1345,x
+ bbs7 $02,*+$34
--- /dev/null
+.setcpu "6502"
+
+ brk
+ ora ($12,x)
+ .byte $02
+ .byte $03
+ .byte $04
+ ora $12
+ asl $12
+ .byte $07
+ php
+ ora #$12
+ asl a
+ .byte $0B
+ .byte $0C
+ ora $3456
+ asl $3456
+ .byte $0F
+ bpl *+122
+ ora ($12),y
+ .byte $12
+ .byte $13
+ .byte $14
+ ora $12,x
+ asl $12,x
+ .byte $17
+ clc
+ ora $3456,y
+ .byte $1A
+ .byte $1B
+ .byte $1C
+ ora $3456,x
+ asl $3456,x
+ .byte $1F
+ jsr $3456
+ and ($12,x)
+ .byte $22
+ .byte $23
+ bit $12
+ and $12
+ rol $12
+ .byte $27
+ plp
+ and #$12
+ rol a
+ .byte $2B
+ bit $3456
+ and $3456
+ rol $3456
+ .byte $2F
+ bmi *+122
+ and ($12),y
+ .byte $32
+ .byte $33
+ .byte $34
+ and $12,x
+ rol $12,x
+ .byte $37
+ sec
+ and $3456,y
+ .byte $3A
+ .byte $3B
+ .byte $3C
+ and $3456,x
+ rol $3456,x
+ .byte $3F
+ rti
+ eor ($12,x)
+ .byte $42
+ .byte $43
+ .byte $44
+ eor $12
+ lsr $12
+ .byte $47
+ pha
+ eor #$12
+ lsr a
+ .byte $4B
+ jmp $3456
+ eor $3456
+ lsr $3456
+ .byte $4F
+ bvc *+122
+ eor ($12),y
+ .byte $52
+ .byte $53
+ .byte $54
+ eor $12,x
+ lsr $12,x
+ .byte $57
+ cli
+ eor $3456,y
+ .byte $5A
+ .byte $5B
+ .byte $5C
+ eor $3456,x
+ lsr $3456,x
+ .byte $5F
+ rts
+ adc ($12,x)
+ .byte $62
+ .byte $63
+ .byte $64
+ adc $12
+ ror $12
+ .byte $67
+ pla
+ adc #$12
+ ror a
+ .byte $6B
+ jmp ($3456)
+ adc $3456
+ ror $3456
+ .byte $6F
+ bvs *+122
+ adc ($12),y
+ .byte $72
+ .byte $73
+ .byte $74
+ adc $12,x
+ ror $12,x
+ .byte $77
+ sei
+ adc $3456,y
+ .byte $7A
+ .byte $7B
+ .byte $7C
+ adc $3456,x
+ ror $3456,x
+ .byte $7F
+ .byte $80
+ sta ($12,x)
+ .byte $82
+ .byte $83
+ sty $12
+ sta $12
+ stx $12
+ .byte $87
+ dey
+ .byte $89
+ txa
+ .byte $8B
+ sty $3456
+ sta $3456
+ stx $3456
+ .byte $8F
+ bcc *+122
+ sta ($12),y
+ .byte $92
+ .byte $93
+ sty $12,x
+ sta $12,x
+ stx $12,y
+ .byte $97
+ tya
+ sta $3456,y
+ txs
+ .byte $9B
+ .byte $9C
+ sta $3456,x
+ .byte $9E
+ .byte $9F
+ ldy #$12
+ lda ($12,x)
+ ldx #$12
+ .byte $A3
+ ldy $12
+ lda $12
+ ldx $12
+ .byte $A7
+ tay
+ lda #$12
+ tax
+ .byte $AB
+ ldy $3456
+ lda $3456
+ ldx $3456
+ .byte $AF
+ bcs *+122
+ lda ($12),y
+ .byte $B2
+ .byte $B3
+ ldy $12,x
+ lda $12,x
+ ldx $12,y
+ .byte $B7
+ clv
+ lda $3456,y
+ tsx
+ .byte $BB
+ ldy $3456,x
+ lda $3456,x
+ ldx $3456,y
+ .byte $BF
+ cpy #$12
+ cmp ($12,x)
+ .byte $C2
+ .byte $C3
+ cpy $12
+ cmp $12
+ dec $12
+ .byte $C7
+ iny
+ cmp #$12
+ dex
+ .byte $CB
+ cpy $3456
+ cmp $3456
+ dec $3456
+ .byte $CF
+ bne *+122
+ cmp ($12),y
+ .byte $D2
+ .byte $D3
+ .byte $D4
+ cmp $12,x
+ dec $12,x
+ .byte $D7
+ cld
+ cmp $3456,y
+ .byte $DA
+ .byte $DB
+ .byte $DC
+ cmp $3456,x
+ dec $3456,x
+ .byte $DF
+ cpx #$12
+ sbc ($12,x)
+ .byte $E2
+ .byte $E3
+ cpx $12
+ sbc $12
+ inc $12
+ .byte $E7
+ inx
+ sbc #$12
+ .byte $EB
+ cpx $3456
+ sbc $3456
+ inc $3456
+ .byte $EF
+ beq *+122
+ sbc ($12),y
+ .byte $F2
+ .byte $F3
+ .byte $F4
+ sbc $12,x
+ inc $12,x
+ .byte $F7
+ sed
+ sbc $3456,y
+ .byte $FA
+ .byte $FB
+ .byte $FC
+ sbc $3456,x
+ inc $3456,x
+ .byte $FF
--- /dev/null
+.setcpu "6502X"
+
+ brk
+ ora ($12,x)
+ jam
+ slo ($12,x)
+ nop $12
+ ora $12
+ asl $12
+ slo $12
+ php
+ ora #$12
+ asl a
+ anc #$12
+ nop $3456
+ ora $3456
+ asl $3456
+ slo $3456
+ bpl *+122
+ ora ($12),y
+ .byte $12 ; jam
+ slo ($12),y
+ nop $12,x
+ ora $12,x
+ asl $12,x
+ slo $12,x
+ clc
+ ora $3456,y
+ .byte $1a ; nop
+ slo $3456,y
+ nop $3456,x
+ ora $3456,x
+ asl $3456,x
+ slo $3456,x
+ jsr $3456
+ and ($12,x)
+ .byte $22 ; jam
+ rla ($12,x)
+ bit $12
+ and $12
+ rol $12
+ rla $12
+ plp
+ and #$12
+ rol a
+ .byte $2b ; anc #$12
+ bit $3456
+ and $3456
+ rol $3456
+ rla $3456
+ bmi *+122
+ and ($12),y
+ .byte $32 ; jam
+ rla ($12),y
+ .byte $34,$12 ; nop $12,x
+ and $12,x
+ rol $12,x
+ rla $12,x
+ sec
+ and $3456,y
+ .byte $3a ; nop
+ rla $3456,y
+ .byte $3c,$56,$34 ; nop $3456,x
+ and $3456,x
+ rol $3456,x
+ rla $3456,x
+ rti
+ eor ($12,x)
+ .byte $42 ; jam
+ sre ($12,x)
+ .byte $44,$12 ; nop $12
+ eor $12
+ lsr $12
+ sre $12
+ pha
+ eor #$12
+ lsr a
+ alr #$12
+ jmp $3456
+ eor $3456
+ lsr $3456
+ sre $3456
+ bvc *+122
+ eor ($12),y
+ .byte $52 ; jam
+ sre ($12),y
+ .byte $54,$12 ; nop $12,x
+ eor $12,x
+ lsr $12,x
+ sre $12,x
+ cli
+ eor $3456,y
+ .byte $5a ; nop
+ sre $3456,y
+ nop $3456,x
+ eor $3456,x
+ lsr $3456,x
+ sre $3456,x
+ rts
+ adc ($12,x)
+ .byte $62 ; jam
+ rra ($12,x)
+ .byte $64,$12 ; nop $12
+ adc $12
+ ror $12
+ rra $12
+ pla
+ adc #$12
+ ror a
+ arr #$12
+ jmp ($3456)
+ adc $3456
+ ror $3456
+ rra $3456
+ bvs *+122
+ adc ($12),y
+ .byte $72 ; jam
+ rra ($12),y
+ .byte $74,$12 ; nop $12,x
+ adc $12,x
+ ror $12,x
+ rra $12,x
+ sei
+ adc $3456,y
+ .byte $7a ; nop
+ rra $3456,y
+ .byte $7c,$56,$34 ; nop $3456,x
+ adc $3456,x
+ ror $3456,x
+ rra $3456,x
+ nop #$12
+ sta ($12,x)
+ .byte $82,$12 ; nop #$12
+ sax ($12,x)
+ sty $12
+ sta $12
+ stx $12
+ sax $12
+ dey
+ .byte $89,$12 ; nop #$12
+ txa
+ .byte $8b,$12 ; xaa #$12
+ sty $3456
+ sta $3456
+ stx $3456
+ sax $3456
+ bcc *+122
+ sta ($12),y
+ .byte $92 ; jam
+ .byte $93,$12 ; ahx ($12),y
+ sty $12,x
+ sta $12,x
+ stx $12,y
+ sax $12,y
+ tya
+ sta $3456,y
+ txs
+ tas $3456,y
+ shy $3456,x
+ sta $3456,x
+ shx $3456,y
+ .byte $9f,$56,$34 ; ahx $3456,y
+ ldy #$12
+ lda ($12,x)
+ ldx #$12
+ lax ($12,x)
+ ldy $12
+ lda $12
+ ldx $12
+ lax $12
+ tay
+ lda #$12
+ tax
+ lax #$12
+ ldy $3456
+ lda $3456
+ ldx $3456
+ lax $3456
+ bcs *+122
+ lda ($12),y
+ .byte $b2 ; jam
+ lax ($12),y
+ ldy $12,x
+ lda $12,x
+ ldx $12,y
+ lax $12,y
+ clv
+ lda $3456,y
+ tsx
+ las $3456,y
+ ldy $3456,x
+ lda $3456,x
+ ldx $3456,y
+ lax $3456,y
+ cpy #$12
+ cmp ($12,x)
+ .byte $c2,$12 ; nop #$12
+ dcp ($12,x)
+ cpy $12
+ cmp $12
+ dec $12
+ dcp $12
+ iny
+ cmp #$12
+ dex
+ axs #$12
+ cpy $3456
+ cmp $3456
+ dec $3456
+ dcp $3456
+ bne *+122
+ cmp ($12),y
+ .byte $d2 ; jam
+ dcp ($12),y
+ .byte $d4,$12 ; nop $12,x
+ cmp $12,x
+ dec $12,x
+ dcp $12,x
+ cld
+ cmp $3456,y
+ .byte $da ; nop
+ dcp $3456,y
+ .byte $dc,$56,$34 ; nop $3456,x
+ cmp $3456,x
+ dec $3456,x
+ dcp $3456,x
+ cpx #$12
+ sbc ($12,x)
+ .byte $e2,$12 ; nop #$12
+ isc ($12,x)
+ cpx $12
+ sbc $12
+ inc $12
+ isc $12
+ inx
+ sbc #$12
+ nop
+ .byte $eb ; nop
+ cpx $3456
+ sbc $3456
+ inc $3456
+ isc $3456
+ beq *+122
+ sbc ($12),y
+ .byte $f2 ; jam
+ isc ($12),y
+ .byte $f4,$12 ; nop $12,x
+ sbc $12,x
+ inc $12,x
+ isc $12,x
+ sed
+ sbc $3456,y
+ .byte $fa ; nop
+ isc $3456,y
+ .byte $fc,$56,$34 ; nop $3456,x
+ sbc $3456,x
+ inc $3456,x
+ isc $3456,x
--- /dev/null
+.setcpu "65C02"
+
+ brk
+ ora ($12,x)
+ .byte $02
+ .byte $03
+ tsb $12
+ ora $12
+ asl $12
+ rmb0 $12
+ php
+ ora #$12
+ asl a
+ .byte $0B
+ tsb $3456
+ ora $3456
+ asl $3456
+ bbr0 $12,*+122
+ bpl *+122
+ ora ($12),y
+ ora ($12)
+ .byte $13
+ trb $12
+ ora $12,x
+ asl $12,x
+ rmb1 $12
+ clc
+ ora $3456,y
+ inc a
+ .byte $1B
+ trb $3456
+ ora $3456,x
+ asl $3456,x
+ bbr1 $12,*+122
+ jsr $3456
+ and ($12,x)
+ .byte $22
+ .byte $23
+ bit $12
+ and $12
+ rol $12
+ rmb2 $12
+ plp
+ and #$12
+ rol a
+ .byte $2B
+ bit $3456
+ and $3456
+ rol $3456
+ bbr2 $12,*+122
+ bmi *+122
+ and ($12),y
+ and ($12)
+ .byte $33
+ bit $12,x
+ and $12,x
+ rol $12,x
+ rmb3 $12
+ sec
+ and $3456,y
+ dec a
+ .byte $3B
+ bit $3456,x
+ and $3456,x
+ rol $3456,x
+ bbr3 $12,*+122
+ rti
+ eor ($12,x)
+ .byte $42
+ .byte $43
+ .byte $44
+ eor $12
+ lsr $12
+ rmb4 $12
+ pha
+ eor #$12
+ lsr a
+ .byte $4B
+ jmp $3456
+ eor $3456
+ lsr $3456
+ bbr4 $12,*+122
+ bvc *+122
+ eor ($12),y
+ eor ($12)
+ .byte $53
+ .byte $54
+ eor $12,x
+ lsr $12,x
+ rmb5 $12
+ cli
+ eor $3456,y
+ phy
+ .byte $5B
+ .byte $5C
+ eor $3456,x
+ lsr $3456,x
+ bbr5 $12,*+122
+ rts
+ adc ($12,x)
+ .byte $62
+ .byte $63
+ stz $12
+ adc $12
+ ror $12
+ rmb6 $12
+ pla
+ adc #$12
+ ror a
+ .byte $6B
+ jmp ($3456)
+ adc $3456
+ ror $3456
+ bbr6 $12,*+122
+ bvs *+122
+ adc ($12),y
+ adc ($12)
+ .byte $73
+ stz $12,x
+ adc $12,x
+ ror $12,x
+ rmb7 $12
+ sei
+ adc $3456,y
+ ply
+ .byte $7B
+ jmp ($3456,x)
+ adc $3456,x
+ ror $3456,x
+ bbr7 $12,*+122
+ bra *+122
+ sta ($12,x)
+ .byte $82
+ .byte $83
+ sty $12
+ sta $12
+ stx $12
+ smb0 $12
+ dey
+ bit #$12
+ txa
+ .byte $8B
+ sty $3456
+ sta $3456
+ stx $3456
+ bbs0 $12,*+122
+ bcc *+122
+ sta ($12),y
+ sta ($12)
+ .byte $93
+ sty $12,x
+ sta $12,x
+ stx $12,y
+ smb1 $12
+ tya
+ sta $3456,y
+ txs
+ .byte $9B
+ stz $3456
+ sta $3456,x
+ stz $3456,x
+ bbs1 $12,*+122
+ ldy #$12
+ lda ($12,x)
+ ldx #$12
+ .byte $A3
+ ldy $12
+ lda $12
+ ldx $12
+ smb2 $12
+ tay
+ lda #$12
+ tax
+ .byte $AB
+ ldy $3456
+ lda $3456
+ ldx $3456
+ bbs2 $12,*+122
+ bcs *+122
+ lda ($12),y
+ lda ($12)
+ .byte $B3
+ ldy $12,x
+ lda $12,x
+ ldx $12,y
+ smb3 $12
+ clv
+ lda $3456,y
+ tsx
+ .byte $BB
+ ldy $3456,x
+ lda $3456,x
+ ldx $3456,y
+ bbs3 $12,*+122
+ cpy #$12
+ cmp ($12,x)
+ .byte $C2
+ .byte $C3
+ cpy $12
+ cmp $12
+ dec $12
+ smb4 $12
+ iny
+ cmp #$12
+ dex
+ .byte $CB
+ cpy $3456
+ cmp $3456
+ dec $3456
+ bbs4 $12,*+122
+ bne *+122
+ cmp ($12),y
+ cmp ($12)
+ .byte $D3
+ .byte $D4
+ cmp $12,x
+ dec $12,x
+ smb5 $12
+ cld
+ cmp $3456,y
+ phx
+ .byte $DB
+ .byte $DC
+ cmp $3456,x
+ dec $3456,x
+ bbs5 $12,*+122
+ cpx #$12
+ sbc ($12,x)
+ .byte $E2
+ .byte $E3
+ cpx $12
+ sbc $12
+ inc $12
+ smb6 $12
+ inx
+ sbc #$12
+ nop
+ .byte $EB
+ cpx $3456
+ sbc $3456
+ inc $3456
+ bbs6 $12,*+122
+ beq *+122
+ sbc ($12),y
+ sbc ($12)
+ .byte $F3
+ .byte $F4
+ sbc $12,x
+ inc $12,x
+ smb7 $12
+ sed
+ sbc $3456,y
+ plx
+ .byte $FB
+ .byte $FC
+ sbc $3456,x
+ inc $3456,x
+ bbs7 $12,*+122
--- /dev/null
+.setcpu "65SC02"
+
+ brk
+ ora ($12,x)
+ .byte $02
+ .byte $03
+ tsb $12
+ ora $12
+ asl $12
+ .byte $07
+ php
+ ora #$12
+ asl a
+ .byte $0B
+ tsb $3456
+ ora $3456
+ asl $3456
+ .byte $0F
+ bpl *+122
+ ora ($12),y
+ ora ($12)
+ .byte $13
+ trb $12
+ ora $12,x
+ asl $12,x
+ .byte $17
+ clc
+ ora $3456,y
+ inc a
+ .byte $1B
+ trb $3456
+ ora $3456,x
+ asl $3456,x
+ .byte $1F
+ jsr $3456
+ and ($12,x)
+ .byte $22
+ .byte $23
+ bit $12
+ and $12
+ rol $12
+ .byte $27
+ plp
+ and #$12
+ rol a
+ .byte $2B
+ bit $3456
+ and $3456
+ rol $3456
+ .byte $2F
+ bmi *+122
+ and ($12),y
+ and ($12)
+ .byte $33
+ bit $12,x
+ and $12,x
+ rol $12,x
+ .byte $37
+ sec
+ and $3456,y
+ dec a
+ .byte $3B
+ bit $3456,x
+ and $3456,x
+ rol $3456,x
+ .byte $3F
+ rti
+ eor ($12,x)
+ .byte $42
+ .byte $43
+ .byte $44
+ eor $12
+ lsr $12
+ .byte $47
+ pha
+ eor #$12
+ lsr a
+ .byte $4B
+ jmp $3456
+ eor $3456
+ lsr $3456
+ .byte $4F
+ bvc *+122
+ eor ($12),y
+ eor ($12)
+ .byte $53
+ .byte $54
+ eor $12,x
+ lsr $12,x
+ .byte $57
+ cli
+ eor $3456,y
+ phy
+ .byte $5B
+ .byte $5C
+ eor $3456,x
+ lsr $3456,x
+ .byte $5F
+ rts
+ adc ($12,x)
+ .byte $62
+ .byte $63
+ stz $12
+ adc $12
+ ror $12
+ .byte $67
+ pla
+ adc #$12
+ ror a
+ .byte $6B
+ jmp ($3456)
+ adc $3456
+ ror $3456
+ .byte $6F
+ bvs *+122
+ adc ($12),y
+ adc ($12)
+ .byte $73
+ stz $12,x
+ adc $12,x
+ ror $12,x
+ .byte $77
+ sei
+ adc $3456,y
+ ply
+ .byte $7B
+ jmp ($3456,x)
+ adc $3456,x
+ ror $3456,x
+ .byte $7F
+ bra *+122
+ sta ($12,x)
+ .byte $82
+ .byte $83
+ sty $12
+ sta $12
+ stx $12
+ .byte $87
+ dey
+ bit #$12
+ txa
+ .byte $8B
+ sty $3456
+ sta $3456
+ stx $3456
+ .byte $8F
+ bcc *+122
+ sta ($12),y
+ sta ($12)
+ .byte $93
+ sty $12,x
+ sta $12,x
+ stx $12,y
+ .byte $97
+ tya
+ sta $3456,y
+ txs
+ .byte $9B
+ stz $3456
+ sta $3456,x
+ stz $3456,x
+ .byte $9F
+ ldy #$12
+ lda ($12,x)
+ ldx #$12
+ .byte $A3
+ ldy $12
+ lda $12
+ ldx $12
+ .byte $A7
+ tay
+ lda #$12
+ tax
+ .byte $AB
+ ldy $3456
+ lda $3456
+ ldx $3456
+ .byte $AF
+ bcs *+122
+ lda ($12),y
+ lda ($12)
+ .byte $B3
+ ldy $12,x
+ lda $12,x
+ ldx $12,y
+ .byte $B7
+ clv
+ lda $3456,y
+ tsx
+ .byte $BB
+ ldy $3456,x
+ lda $3456,x
+ ldx $3456,y
+ .byte $BF
+ cpy #$12
+ cmp ($12,x)
+ .byte $C2
+ .byte $C3
+ cpy $12
+ cmp $12
+ dec $12
+ .byte $C7
+ iny
+ cmp #$12
+ dex
+ .byte $CB
+ cpy $3456
+ cmp $3456
+ dec $3456
+ .byte $CF
+ bne *+122
+ cmp ($12),y
+ cmp ($12)
+ .byte $D3
+ .byte $D4
+ cmp $12,x
+ dec $12,x
+ .byte $D7
+ cld
+ cmp $3456,y
+ phx
+ .byte $DB
+ .byte $DC
+ cmp $3456,x
+ dec $3456,x
+ .byte $DF
+ cpx #$12
+ sbc ($12,x)
+ .byte $E2
+ .byte $E3
+ cpx $12
+ sbc $12
+ inc $12
+ .byte $E7
+ inx
+ sbc #$12
+ nop
+ .byte $EB
+ cpx $3456
+ sbc $3456
+ inc $3456
+ .byte $EF
+ beq *+122
+ sbc ($12),y
+ sbc ($12)
+ .byte $F3
+ .byte $F4
+ sbc $12,x
+ inc $12,x
+ .byte $F7
+ sed
+ sbc $3456,y
+ plx
+ .byte $FB
+ .byte $FC
+ sbc $3456,x
+ inc $3456,x
+ .byte $FF
--- /dev/null
+
+# makefile for the assembler regression tests
+
+BINDIR = ../../bin
+WORKDIR := ../../testwrk
+
+BASE_TARGETS = 6502 6502x 65sc02 65c02
+BASE_TARGETS += 4510 huc6280
+
+OPCODE_TARGETS = $(BASE_TARGETS)
+CPUDETECT_TARGETS = $(BASE_TARGETS)
+
+CPUDETECT_TARGETS += 65816
+
+# default target defined later
+all:
+
+# generate opcode targets and expand target list
+define opcode
+OPCODE_TARGETLIST += $$(WORKDIR)/$(1)-opcodes.bin
+$$(WORKDIR)/$(1)-opcodes.bin: $(1)-opcodes.s
+ @$$(BINDIR)/cl65 --cpu $(1) -t none -l $$(WORKDIR)/$(1)-opcodes.lst --obj-path $$(WORKDIR) -o $$@ $$<
+ @diff -q $(1)-opcodes.ref $$@ || (cat $$(WORKDIR)/$(1)-opcodes.lst ; exit 1)
+ @echo ca65 --cpu $(1) opcodes ok
+ @rm -f $(1)-opcodes.o #workaround for #168
+endef
+$(foreach target,$(OPCODE_TARGETS),$(eval $(call opcode,$(target))))
+
+# generate cpudetect targets and expand target list
+define cpudetect
+CPUDETECT_TARGETLIST += $$(WORKDIR)/$(1)-cpudetect.bin
+$$(WORKDIR)/$(1)-cpudetect.bin: cpudetect.s
+ @$$(BINDIR)/cl65 --cpu $(1) -t none -l $$(WORKDIR)/$(1)-cpudetect.lst --obj-path $$(WORKDIR) -o $$@ $$<
+ @diff -q $(1)-cpudetect.ref $$@ || (cat $$(WORKDIR)/$(1)-cpudetect.lst ; exit 1)
+ @echo ca65 --cpu $(1) cpudetect ok
+ @rm -f cpudetect.o #workaround for #168
+endef
+$(foreach target,$(CPUDETECT_TARGETS),$(eval $(call cpudetect,$(target))))
+
+# now that all targets have been generated, get to the manual ones
+all: $(OPCODE_TARGETLIST) $(CPUDETECT_TARGETLIST)
+ @#
+
+.PHONY: all $(OPCODE_TARGETLIST) $(CPUDETECT_TARGETLIST)
+
--- /dev/null
+
+Assembler Testcases
+===================
+
+Opcode Tests:
+-------------
+
+These testcases are inspired by the ones now removed from test/assembler.
+The main purpose is to have each possible opcode generated at least once,
+either by an assembly instruction or a ".byte"-placeholder. Typically
+generated by disassembling a binary dump that contains data in the form
+of the pattern that each opcode is stated once in order followed by easy
+to recognise:
+
+00 00 EA 00
+01 00 EA 00
+02 00 EA 00
+[...]
+fe 00 EA 00
+ff 00 EA 00
+
+The disassembly is then put in a better readable form by replacing the
+leftover dummy opcode parameters with something more recognizable.
+
+The testcases for 6502, 6502x, 65sc02, 65c02, 4510, and huc6280 have been
+put together by Sven Oliver ("SvOlli") Moll, as well as a template for the
+m740 instructions set.
+
+Still to do is to find a way to implement an opcode testcase for the 65816
+processor, since it's capable of executing instructions with an 8-bit and
+a 16-bit operator alike, only distinguished by one processor flag.
+
+
+CPU detect Tests
+----------------
+
+These tests all assemble the same file "cpudetect.s" which contains several
+conditionals for several CPUs, only using every option known to the "--cpu"
+commandline switch of ca65/cl65.
+
+
+Reference (".ref") Files
+------------------------
+
+A hint on creating these files: when running the test, it will fail due to
+the missing ".ref" file. Review the output of the ".lst" very pedantic, then
+copy the ".bin" to the ".ref" file.
+
--- /dev/null
+
+.macpack cpu
+
+; step 1: try to assemble an instruction that's exclusive to this set
+; (when possible)
+
+.ifp02
+ lda #$ea
+.endif
+
+.ifpsc02
+ jmp ($1234,x)
+.endif
+
+.ifpc02
+ rmb0 $12
+.endif
+
+.ifp816
+ xba
+.endif
+
+.ifp4510
+ taz
+.endif
+
+
+; step 2: check for bitwise compatibility of instructions sets
+; (made verbose for better reading with hexdump/hd(1))
+
+.if (.cpu .bitand CPU_ISET_NONE)
+ .byte 0,"CPU_ISET_NONE"
+.endif
+
+.if (.cpu .bitand CPU_ISET_6502)
+ .byte 0,"CPU_ISET_6502"
+.endif
+
+.if (.cpu .bitand CPU_ISET_6502X)
+ .byte 0,"CPU_ISET_6502X"
+.endif
+
+.if (.cpu .bitand CPU_ISET_65SC02)
+ .byte 0,"CPU_ISET_65SC02"
+.endif
+
+.if (.cpu .bitand CPU_ISET_65C02)
+ .byte 0,"CPU_ISET_65C02"
+.endif
+
+.if (.cpu .bitand CPU_ISET_65816)
+ .byte 0,"CPU_ISET_65816"
+.endif
+
+.if (.cpu .bitand CPU_ISET_SWEET16)
+ .byte 0,"CPU_ISET_SWEET16"
+.endif
+
+.if (.cpu .bitand CPU_ISET_HUC6280)
+ .byte 0,"CPU_ISET_HUC6280"
+.endif
+
+.if (.cpu .bitand CPU_ISET_4510)
+ .byte 0,"CPU_ISET_4510"
+.endif
+
--- /dev/null
+.setcpu "huc6280"
+
+ brk
+ ora ($12,x)
+ sxy
+ st0 #$12
+ tsb $12
+ ora $12
+ asl $12
+ rmb0 $12
+ php
+ ora #$12
+ asl a
+ .byte $0B
+ tsb $3456
+ ora $3456
+ asl $3456
+ bbr0 $12,*+122
+ bpl *+122
+ ora ($12),y
+ ora ($12)
+ st1 #$12
+ trb $12
+ ora $12,x
+ asl $12,x
+ rmb1 $12
+ clc
+ ora $3456,y
+ inc a
+ .byte $1B
+ trb $3456
+ ora $3456,x
+ asl $3456,x
+ bbr1 $12,*+122
+ jsr $3456
+ and ($12,x)
+ sax
+ st2 #$12
+ bit $12
+ and $12
+ rol $12
+ rmb2 $12
+ plp
+ and #$12
+ rol a
+ .byte $2B
+ bit $3456
+ and $3456
+ rol $3456
+ bbr2 $12,*+122
+ bmi *+122
+ and ($12),y
+ and ($12)
+ .byte $33
+ bit $12,x
+ and $12,x
+ rol $12,x
+ rmb3 $12
+ sec
+ and $3456,y
+ dec a
+ .byte $3B
+ bit $3456,x
+ and $3456,x
+ rol $3456,x
+ bbr3 $12,*+122
+ rti
+ eor ($12,x)
+ say
+ tma #$02
+ bsr *+122
+ eor $12
+ lsr $12
+ rmb4 $12
+ pha
+ eor #$12
+ lsr a
+ .byte $4B
+ jmp $3456
+ eor $3456
+ lsr $3456
+ bbr4 $12,*+122
+ bvc *+122
+ eor ($12),y
+ eor ($12)
+ tam #$12
+ csl
+ eor $12,x
+ lsr $12,x
+ rmb5 $12
+ cli
+ eor $3456,y
+ phy
+ .byte $5B
+ .byte $5C
+ eor $3456,x
+ lsr $3456,x
+ bbr5 $12,*+122
+ rts
+ adc ($12,x)
+ cla
+ .byte $63
+ stz $12
+ adc $12
+ ror $12
+ rmb6 $12
+ pla
+ adc #$12
+ ror a
+ .byte $6B
+ jmp ($3456)
+ adc $3456
+ ror $3456
+ bbr6 $12,*+122
+ bvs *+122
+ adc ($12),y
+ adc ($12)
+ tii $3333,$7373,$1111
+ stz $12,x
+ adc $12,x
+ ror $12,x
+ rmb7 $12
+ sei
+ adc $3456,y
+ ply
+ .byte $7B
+ jmp ($3456,x)
+ adc $3456,x
+ ror $3456,x
+ bbr7 $12,*+122
+ bra *+122
+ sta ($12,x)
+ clx
+ tst #$12,$EA
+ sty $12
+ sta $12
+ stx $12
+ smb0 $12
+ dey
+ bit #$12
+ txa
+ .byte $8B
+ sty $3456
+ sta $3456
+ stx $3456
+ bbs0 $12,*+122
+ bcc *+122
+ sta ($12),y
+ sta ($12)
+ tst #$12,$EAEA
+ sty $12,x
+ sta $12,x
+ stx $12,y
+ smb1 $12
+ tya
+ sta $3456,y
+ txs
+ .byte $9B
+ stz $3456
+ sta $3456,x
+ stz $3456,x
+ bbs1 $12,*+122
+ ldy #$12
+ lda ($12,x)
+ ldx #$12
+ tst #$12,$EA,x
+ ldy $12
+ lda $12
+ ldx $12
+ smb2 $12
+ tay
+ lda #$12
+ tax
+ .byte $AB
+ ldy $3456
+ lda $3456
+ ldx $3456
+ bbs2 $12,*+122
+ bcs *+122
+ lda ($12),y
+ lda ($12)
+ tst #$12,$EAEA,x
+ ldy $12,x
+ lda $12,x
+ ldx $12,y
+ smb3 $12
+ clv
+ lda $3456,y
+ tsx
+ .byte $BB
+ ldy $3456,x
+ lda $3456,x
+ ldx $3456,y
+ bbs3 $12,*+122
+ cpy #$12
+ cmp ($12,x)
+ cly
+ tdd $3333,$C3C3,$1111
+ cpy $12
+ cmp $12
+ dec $12
+ smb4 $12
+ iny
+ cmp #$12
+ dex
+ .byte $CB
+ cpy $3456
+ cmp $3456
+ dec $3456
+ bbs4 $12,*+122
+ bne *+122
+ cmp ($12),y
+ cmp ($12)
+ tin $3333,$D3D3,$1111
+ .byte $D4
+ cmp $12,x
+ dec $12,x
+ smb5 $12
+ cld
+ cmp $3456,y
+ phx
+ .byte $DB
+ .byte $DC
+ cmp $3456,x
+ dec $3456,x
+ bbs5 $12,*+122
+ cpx #$12
+ sbc ($12,x)
+ .byte $E2
+ tia $3333,$E3E3,$1111
+ cpx $12
+ sbc $12
+ inc $12
+ smb6 $12
+ inx
+ sbc #$12
+ nop
+ .byte $EB
+ cpx $3456
+ sbc $3456
+ inc $3456
+ bbs6 $12,*+122
+ beq *+122
+ sbc ($12),y
+ sbc ($12)
+ tai $3333,$F3F3,$1111
+ .byte $F4
+ sbc $12,x
+ inc $12,x
+ smb7 $12
+ sed
+ sbc $3456,y
+ plx
+ .byte $FB
+ .byte $FC
+ sbc $3456,x
+ inc $3456,x
+ bbs7 $12,*+122
--- /dev/null
+.setcpu "65C02"
+; copy of 65c02, comments note changes to the m740 according to
+; http://documentation.renesas.com/doc/products/mpumcu/rej09b0322_740sm.pdf
+
+ brk
+ ora ($12,x)
+ .byte $02,$00,$00 ; jsr zp,ind
+ .byte $03,$00,$00 ; bbs 0,a
+ tsb $12 ; .byte $04
+ ora $12
+ asl $12
+ rmb0 $12 ; bbs 0,zp
+ php
+ ora #$12
+ asl a
+ .byte $0B,$00,$00 ; seb 0,a
+ tsb $3456 ; .byte $0c
+ ora $3456
+ asl $3456
+ bbr0 $12,*+122 ; seb 0,zp
+ bpl *+122
+ ora ($12),y
+ ora ($12) ; clt
+ .byte $13,$00,$00 ; bbc 0,a
+ trb $12 ; .byte $14
+ ora $12,x
+ asl $12,x
+ rmb1 $12 ; bbc 0,zp
+ clc
+ ora $3456,y
+ inc a
+ .byte $1B,$00,$00 ; clb 0,a
+ trb $3456 ; .byte $1c
+ ora $3456,x
+ asl $3456,x
+ bbr1 $12,*+122 ; clb 0,zp
+ jsr $3456
+ and ($12,x)
+ .byte $22,$00,$00 ; jsr sp
+ .byte $23,$00,$00 ; bbs 1,a
+ bit $12
+ and $12
+ rol $12
+ rmb2 $12 ; bbs 1,zp
+ plp
+ and #$12
+ rol a
+ .byte $2B,$00,$00 ; seb 1,a
+ bit $3456
+ and $3456
+ rol $3456
+ bbr2 $12,*+122 ; seb 1,zp
+ bmi *+122
+ and ($12),y
+ and ($12) ; set
+ .byte $33,$00,$00 ; bbc 1,a
+ bit $12,x ; .byte $34
+ and $12,x
+ rol $12,x
+ rmb3 $12 ; bbc 1,zp
+ sec
+ and $3456,y
+ dec a
+ .byte $3B,$00,$00 ; clb 1,a
+ bit $3456,x ; ldm zp
+ and $3456,x
+ rol $3456,x
+ bbr3 $12,*+122 ; clb 1,zp
+ rti
+ eor ($12,x)
+ .byte $42,$00,$00 ; stp
+ .byte $43,$00,$00 ; bbs 2,a
+ .byte $44,$00,$00 ; com zp
+ eor $12
+ lsr $12
+ rmb4 $12 ; bbs 2,zp
+ pha
+ eor #$12
+ lsr a
+ .byte $4B,$00,$00 ; seb 2,a
+ jmp $3456
+ eor $3456
+ lsr $3456
+ bbr4 $12,*+122 ; seb 2,zp
+ bvc *+122
+ eor ($12),y
+ eor ($12) ; .byte $52
+ .byte $53,$00,$00 ; bbc 2,a
+ .byte $54,$00,$00
+ eor $12,x
+ lsr $12,x
+ rmb5 $12 ; bbc 2,zp
+ cli
+ eor $3456,y
+ phy
+ .byte $5B,$00,$00 ; clb 2,a
+ .byte $5C,$00,$00
+ eor $3456,x
+ lsr $3456,x
+ bbr5 $12,*+122 ; clb 2,zp
+ rts
+ adc ($12,x)
+ .byte $62,$00,$00 ; mul zp,x
+ .byte $63,$00,$00 ; bbs 3,a
+ stz $12 ; tst zp
+ adc $12
+ ror $12
+ rmb6 $12 ; bbs 3,zp
+ pla
+ adc #$12
+ ror a
+ .byte $6B,$00,$00 ; seb 3,a
+ jmp ($3456)
+ adc $3456
+ ror $3456
+ bbr6 $12,*+122 ; seb 3,zp
+ bvs *+122
+ adc ($12),y
+ adc ($12) ; .byte $72
+ .byte $73,$00,$00 ; bbc 3,a
+ stz $12,x ; .byte $74
+ adc $12,x
+ ror $12,x
+ rmb7 $12 ; bbc 3,zp
+ sei
+ adc $3456,y
+ ply
+ .byte $7B,$00,$00 ; clb 3,a
+ jmp ($3456,x) ; .byte $7c
+ adc $3456,x
+ ror $3456,x
+ bbr7 $12,*+122 ; clb 3,zp
+ bra *+122
+ sta ($12,x)
+ .byte $82,$00,$00 ; rrf zp
+ .byte $83,$00,$00 ; bbs 4,a
+ sty $12
+ sta $12
+ stx $12
+ smb0 $12 ; bbs 4,zp
+ dey
+ bit #$12
+ txa
+ .byte $8B,$00,$00 ; seb 4,a
+ sty $3456
+ sta $3456
+ stx $3456
+ bbs0 $12,*+122 ; seb 4,zp
+ bcc *+122
+ sta ($12),y
+ sta ($12) ; .byte $92
+ .byte $93,$00,$00 ; bbc 4,a
+ sty $12,x
+ sta $12,x
+ stx $12,y
+ smb1 $12 ; bbc 4,zp
+ tya
+ sta $3456,y
+ txs
+ .byte $9B,$00,$00 ; clb 4,a
+ stz $3456 ; .byte $9c
+ sta $3456,x
+ stz $3456,x ; .byte $9e
+ bbs1 $12,*+122 ; clb 4,zp
+ ldy #$12
+ lda ($12,x)
+ ldx #$12
+ .byte $A3,$00,$00 ; bbs 5,a
+ ldy $12
+ lda $12
+ ldx $12
+ smb2 $12 ; bbs 5,zp
+ tay
+ lda #$12
+ tax
+ .byte $AB,$00,$00 ; seb 5,a
+ ldy $3456
+ lda $3456
+ ldx $3456
+ bbs2 $12,*+122 ; seb 5,zp
+ bcs *+122
+ lda ($12),y
+ lda ($12) ; .byte $b2
+ .byte $B3,$00,$00 ; bbc 5,a
+ ldy $12,x
+ lda $12,x
+ ldx $12,y
+ smb3 $12 ; bbc 5,zp
+ clv
+ lda $3456,y
+ tsx
+ .byte $BB,$00,$00 ; clb 5,a
+ ldy $3456,x
+ lda $3456,x
+ ldx $3456,y
+ bbs3 $12,*+122 ; clb 5,zp
+ cpy #$12
+ cmp ($12,x)
+ .byte $C2,$00,$00 ; wit
+ .byte $C3,$00,$00 ; bbs 6,a
+ cpy $12
+ cmp $12
+ dec $12
+ smb4 $12 ; bbs 6,zp
+ iny
+ cmp #$12
+ dex
+ .byte $CB,$00,$00 ; seb 6,a
+ cpy $3456
+ cmp $3456
+ dec $3456
+ bbs4 $12,*+122 ; seb 6,zp
+ bne *+122
+ cmp ($12),y
+ cmp ($12) ; .byte $d2
+ .byte $D3,$00,$00 ; bbc 6,a
+ .byte $D4,$00,$00
+ cmp $12,x
+ dec $12,x
+ smb5 $12 ; bbc 6,zp
+ cld
+ cmp $3456,y
+ phx
+ .byte $DB,$00,$00 ; clb 6,a
+ .byte $DC,$00,$00
+ cmp $3456,x
+ dec $3456,x
+ bbs5 $12,*+122 ; clb 6,zp
+ cpx #$12
+ sbc ($12,x)
+ .byte $E2,$00,$00 ; div zp,x
+ .byte $E3,$00,$00 ; bbs 7,a
+ cpx $12
+ sbc $12
+ inc $12
+ smb6 $12 ; bbs 7,zp
+ inx
+ sbc #$12
+ nop
+ .byte $EB,$00,$00 ; seb 7,a
+ cpx $3456
+ sbc $3456
+ inc $3456
+ bbs6 $12,*+122 ; seb 7,zp
+ beq *+122
+ sbc ($12),y
+ sbc ($12) ; .byte $f2
+ .byte $F3,$00,$00 ; bbc 7,a
+ .byte $F4,$00,$00
+ sbc $12,x
+ inc $12,x
+ smb7 $12 ; bbc 7,zp
+ sed
+ sbc $3456,y
+ plx
+ .byte $FB,$00,$00 ; clb 7,a
+ .byte $FC,$00,$00
+ sbc $3456,x
+ inc $3456,x
+ bbs7 $12,*+122 ; clb 7,zp
--- /dev/null
+.setcpu "4510"
+
+ZP = $12
+ABS = $2345
+
+start:
+ brk
+ ora (ZP,x)
+ cle
+ see
+ tsb ZP
+ ora ZP
+ asl ZP
+ rmb0 ZP
+ php
+ ora #$01
+ asl
+ tsy
+ tsb ABS
+ ora ABS
+ asl ABS
+ bbr0 ZP,label1
+
+label1:
+ bpl label2
+ ora (ZP),y
+ ora (ZP),z
+ lbpl start ; bpl start
+ trb ZP
+ ora ZP,x
+ asl ZP,x
+ rmb1 ZP
+ clc
+ ora ABS,y
+ inc
+ inz
+ trb ABS
+ ora ABS,x
+ asl ABS,x
+ bbr1 ZP,label2
+
+label2:
+ jsr ABS
+ and (ZP,x)
+ jsr ($2345)
+ jsr ($2456,x)
+ bit ZP
+ and ZP
+ rol ZP
+ rmb2 ZP
+ plp
+ and #$01
+ rol
+ tys
+ bit ABS
+ and ABS
+ rol ABS
+ bbr2 ZP,label3
+
+label3:
+ bmi label4
+ and (ZP),y
+ and (ZP),z
+ lbmi start ; bmi start
+ bit ZP,x
+ and ZP,x
+ rol ZP,x
+ rmb3 ZP
+ sec
+ and ABS,y
+ dec
+ dez
+ bit ABS,x
+ and ABS,x
+ rol ABS,x
+ bbr3 ZP,label4
+
+label4:
+ rti
+ eor (ZP,x)
+ neg
+ asr
+ asr ZP
+ eor ZP
+ lsr ZP
+ rmb4 ZP
+ pha
+ eor #$01
+ lsr
+ taz
+ jmp ABS
+ eor ABS
+ lsr ABS
+ bbr4 ZP,label5
+
+label5:
+ bvc label6
+ eor (ZP),y
+ eor (ZP),z
+ lbvc start ; bvc start
+ asr ZP,x
+ eor ZP,x
+ lsr ZP,x
+ rmb5 ZP
+ cli
+ eor ABS,y
+ phy
+ tab
+ map
+ eor ABS,x
+ lsr ABS,x
+ bbr5 ZP,label6
+
+label6:
+ rts
+ adc (ZP,x)
+ rtn #$09
+ bsr start
+ stz ZP
+ adc ZP
+ ror ZP
+ rmb6 ZP
+ pla
+ adc #$01
+ ror
+ tza
+ jmp ($2345)
+ adc ABS
+ ror ABS
+ bbr6 ZP,label7
+
+label7:
+ bvs label8
+ adc (ZP),y
+ adc (ZP),z
+ lbvs start ; bvs start
+ stz ZP,x
+ adc ZP,x
+ ror ZP,x
+ rmb7 ZP
+ sei
+ adc ABS,y
+ ply
+ tba
+ jmp ($2456,x)
+ adc ABS,x
+ ror ABS,x
+ bbr7 ZP,label8
+
+label8:
+ bra label9
+ sta (ZP,x)
+ sta ($0f,sp),y
+ lbra start ; bra start
+ sty ZP
+ sta ZP
+ stx ZP
+ smb0 ZP
+ dey
+ bit #$01
+ txa
+ sty ABS,x
+ sty ABS
+ sta ABS
+ stx ABS
+ bbs0 ZP,label9
+
+label9:
+ bcc labelA
+ sta (ZP),y
+ sta (ZP),z
+ lbcc start ; bcc start
+ sty ZP,x
+ sta ZP,x
+ stx ZP,y
+ smb1 ZP
+ tya
+ sta ABS,y
+ txs
+ stx ABS,y
+ stz ABS
+ sta ABS,x
+ stz ABS,x
+ bbs1 ZP,labelA
+
+labelA:
+ ldy #$01
+ lda (ZP,x)
+ ldx #$01
+ ldz #$01
+ ldy ZP
+ lda ZP
+ ldx ZP
+ smb2 ZP
+ tay
+ lda #$01
+ tax
+ ldz ABS
+ ldy ABS
+ lda ABS
+ ldx ABS
+ bbs2 ZP,labelB
+
+labelB:
+ bcs labelC
+ lda (ZP),y
+ lda (ZP),z
+ lbcs start ; bcs start
+ ldy ZP,x
+ lda ZP,x
+ ldx ZP,y
+ smb3 ZP
+ clv
+ lda ABS,y
+ tsx
+ ldz ABS,x
+ ldy ABS,x
+ lda ABS,x
+ ldx ABS,y
+ bbs3 ZP,labelC
+
+labelC:
+ cpy #$01
+ cmp (ZP,x)
+ cpz #$01
+ dew ZP
+ cpy ZP
+ cmp ZP
+ dec ZP
+ smb4 ZP
+ iny
+ cmp #$01
+ dex
+ asw ABS
+ cpy ABS
+ cmp ABS
+ dec ABS
+ bbs4 ZP,labelD
+
+labelD:
+ bne labelE
+ cmp (ZP),y
+ cmp (ZP),z
+ lbne start ; bne start
+ cpz ZP
+ cmp ZP,x
+ dec ZP,x
+ smb5 ZP
+ cld
+ cmp ABS,y
+ phx
+ phz
+ cpz ABS
+ cmp ABS,x
+ dec ABS,x
+ bbs5 ZP,labelE
+
+labelE:
+ cpx #$01
+ sbc (ZP,x)
+ lda ($0f,sp),y
+ inw ZP
+ cpx ZP
+ sbc ZP
+ inc ZP
+ smb6 ZP
+ inx
+ sbc #$01
+ eom
+ nop
+ row ABS
+ cpx ABS
+ sbc ABS
+ inc ABS
+ bbs6 ZP,labelF
+
+labelF:
+ beq labelG
+ sbc (ZP),y
+ sbc (ZP),z
+ lbeq start ; beq start
+ phw #$089a
+ sbc ZP,x
+ inc ZP,x
+ smb7 ZP
+ sed
+ sbc ABS,y
+ plx
+ plz
+ phd ABS
+ phw ABS
+ sbc ABS,x
+ inc ABS,x
+ bbs7 ZP,labelG
+
+labelG:
+ brk
+
--- /dev/null
+
+# makefile for the disassembler regression tests
+
+BINDIR = ../../bin
+WORKDIR := ../../testwrk
+
+#BASE_TARGETS = 6502 6502x 65sc02 65c02
+#BASE_TARGETS += 4510 huc6280
+BASE_TARGETS = 4510
+
+START = --start-addr 0x8000
+
+DISASS_TARGETS = $(BASE_TARGETS)
+
+# default target defined later
+all:
+
+# generate opcode targets and expand target list
+define disass
+DISASS_TARGETLIST += $$(WORKDIR)/$(1)-reass.bin $$(WORKDIR)/$(1)-reass.s $$(WORKDIR)/$(1)-disass.bin
+
+$$(WORKDIR)/$(1)-disass.bin: $(1)-disass.s
+ @$$(BINDIR)/cl65 --cpu $(1) -t none $(START) --obj-path $$(WORKDIR) -o $$@ $$<
+ @rm -f $(1)-disass.o #workaround for #168
+
+$$(WORKDIR)/$(1)-reass.s: $$(WORKDIR)/$(1)-disass.bin
+ @$$(BINDIR)/da65 --cpu $(1) $(START) -o $$@ $$<
+
+$$(WORKDIR)/$(1)-reass.bin: $$(WORKDIR)/$(1)-reass.s
+ @$$(BINDIR)/cl65 --cpu $(1) -t none $(START) --obj-path $$(WORKDIR) -o $$@ $$<
+ @rm -f $(1)-reass.o #workaround for #168
+ @cmp $$@ $$(WORKDIR)/$(1)-disass.bin
+ @echo da65 --cpu $(1) ok
+endef
+$(foreach target,$(DISASS_TARGETS),$(eval $(call disass,$(target))))
+
+# now that all targets have been generated, get to the manual ones
+all: $(DISASS_TARGETLIST)
+ @#
+
+.PHONY: all $(DISASS_TARGETLIST)
+
--- /dev/null
+/*
+ !!DESCRIPTION!! Implementation of Duff's device (loop unrolling).
+ !!ORIGIN!!
+ !!LICENCE!! GPL, read COPYING.GPL
+*/
+
+#include <stdio.h>
+#include <limits.h>
+
+#define ASIZE (100)
+
+unsigned char success=0;
+unsigned char failures=0;
+unsigned char dummy=0;
+
+#ifdef SUPPORT_BIT_TYPES
+bit bit0 = 0;
+#endif
+
+void done()
+{
+ dummy++;
+}
+
+int acmp(char* a, char* b, int count)
+{
+ int i;
+
+ for(i = 0; i < count; i++) {
+ if(a[i] != b[i]) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void duffit (char* to, char* from, int count)
+{
+ int n = (count + 7) / 8;
+
+ switch(count % 8) {
+ case 0: do { *to++ = *from++;
+ case 7: *to++ = *from++;
+ case 6: *to++ = *from++;
+ case 5: *to++ = *from++;
+ case 4: *to++ = *from++;
+ case 3: *to++ = *from++;
+ case 2: *to++ = *from++;
+ case 1: *to++ = *from++;
+ } while(--n > 0);
+ }
+}
+
+int main(void)
+{
+ char a[ASIZE] = {1};
+ char b[ASIZE] = {2};
+
+ /* a and b should be different */
+ if(!acmp(a, b, ASIZE)) {
+ failures++;
+ }
+
+ duffit(a, b, ASIZE);
+
+ /* a and b should be the same */
+ if(acmp(a, b, ASIZE)) {
+ failures++;
+ }
+
+ success=failures;
+ done();
+ printf("failures: %d\n",failures);
+
+ return failures;
+}
--- /dev/null
+/*
+ !!DESCRIPTION!! Testing empty bodied switch statements.
+ !!ORIGIN!!
+ !!LICENCE!! GPL, read COPYING.GPL
+*/
+
+#include <stdio.h>
+
+unsigned char success=0;
+unsigned char failures=0;
+unsigned char dummy=0;
+
+void done()
+{
+ dummy++;
+}
+
+void switch_no_body(void)
+{
+ switch(0);
+}
+
+void switch_empty_body(void)
+{
+ switch(0) {}
+}
+
+/* only worried about this file compiling successfully */
+int main(void)
+{
+ switch_no_body();
+ switch_empty_body();
+
+ success=failures;
+ done();
+ printf("failures: %d\n",failures);
+
+ return failures;
+}
+++ /dev/null
-chkillegal.bin
-chklegal.bin
-chkall.bin
-legal.o
-illegal.o
-all.o
+++ /dev/null
-
-all: chklegal.bin chkillegal.bin chkall.bin
- @#
-
-.PHONY: chklegal.bin chkillegal.bin chkall.bin
-
-chklegal.bin: legal.s
- ../../bin/cl65 --target none --cpu 6502X -o chklegal.bin legal.s
- diff -q legal.ref chklegal.bin || hex chklegal.bin
-
-chkillegal.bin: illegal.s
- ../../bin/cl65 --target none --cpu 6502X -o chkillegal.bin illegal.s
- diff -q illegal.ref chkillegal.bin || hex chkillegal.bin
-
-chkall.bin: all.s
- ../../bin/cl65 --target none --cpu 6502X -o chkall.bin all.s
-
-ref: legal.s illegal.s
- ../../bin/cl65 --target none --cpu 6502X -o legal.ref legal.s
- ../../bin/cl65 --target none --cpu 6502X -o illegal.ref illegal.s
-
-clean:
- rm -f legal.o chklegal.bin
- rm -f illegal.o chkillegal.bin
- rm -f all.o chkall.bin
+++ /dev/null
- .setcpu "6502X"
-
-; all legal and illegal opcodes as they would be disassembled by da65
-; note that this would not assemble into the exact same binary
-
- brk ; 00
- ora ($12,x) ; 01 12
- jam ; 02
- slo ($12,x) ; 03 12
- nop $12 ; 04 12
- ora $12 ; 05 12
- asl $12 ; 06 12
- slo $12 ; 07 12
- php ; 08
- ora #$12 ; 09 12
- asl a ; 0a
- anc #$12 ; 0b 12
- nop $1234 ; 0c 34 12
- ora $1234 ; 0d 34 12
- asl $1234 ; 0e 34 12
- slo $1234 ; 0f 34 12
- bpl *+$14 ; 10 12
- ora ($12),y ; 11 12
- jam ; 12
- slo ($12),y ; 13 12
- nop $12,x ; 14 12
- ora $12,x ; 15 12
- asl $12,x ; 16 12
- slo $12,x ; 17 12
- clc ; 18
- ora $1234,y ; 19 34 12
- nop ; 1a
- slo $1234,y ; 1b 34 12
- nop $1234,x ; 1c 34 12
- ora $1234,x ; 1d 34 12
- asl $1234,x ; 1e 34 12
- slo $1234,x ; 1f 34 12
- jsr $1234 ; 20 34 12
- and ($12,x) ; 21 12
- jam ; 22
- rla ($12,x) ; 23 12
- bit $12 ; 24 12
- and $12 ; 25 12
- rol $12 ; 26 12
- rla $12 ; 27 12
- plp ; 28
- and #$12 ; 29 12
- rol a ; 2a
- anc #$12 ; 2b 12
- bit $1234 ; 2c 34 12
- and $1234 ; 2d 34 12
- rol $1234 ; 2e 34 12
- rla $1234 ; 2f 34 12
- bmi *+$14 ; 30 12
- and ($12),y ; 31 12
- jam ; 32
- rla ($12),y ; 33 12
- nop $12,x ; 34 12
- and $12,x ; 35 12
- rol $12,x ; 36 12
- rla $12,x ; 37 12
- sec ; 38
- and $1234,y ; 39 34 12
- nop ; 3a
- rla $1234,y ; 3b 34 12
- nop $1234,x ; 3c 34 12
- and $1234,x ; 3d 34 12
- rol $1234,x ; 3e 34 12
- rla $1234,x ; 3f 34 12
- rti ; 40
- eor ($12,x) ; 41 12
- jam ; 42
- sre ($12,x) ; 43 12
- nop $12 ; 44 12
- eor $12 ; 45 12
- lsr $12 ; 46 12
- sre $12 ; 47 12
- pha ; 48
- eor #$12 ; 49 12
- lsr a ; 4a
- alr #$12 ; 4b 12
- jmp $1234 ; 4c 34 12
- eor $1234 ; 4d 34 12
- lsr $1234 ; 4e 34 12
- sre $1234 ; 4f 34 12
- bvc *+$14 ; 50 12
- eor ($12),y ; 51 12
- jam ; 52
- sre ($12),y ; 53 12
- nop $12,x ; 54 12
- eor $12,x ; 55 12
- lsr $12,x ; 56 12
- sre $12,x ; 57 12
- cli ; 58
- eor $1234,y ; 59 34 12
- nop ; 5a
- sre $1234,y ; 5b 34 12
- nop $1234,x ; 5c 34 12
- eor $1234,x ; 5d 34 12
- lsr $1234,x ; 5e 34 12
- sre $1234,x ; 5f 34 12
- rts ; 60
- adc ($12,x) ; 61 12
- jam ; 62
- rra ($12,x) ; 63 12
- nop $12 ; 64 12
- adc $12 ; 65 12
- ror $12 ; 66 12
- rra $12 ; 67 12
- pla ; 68
- adc #$12 ; 69 12
- ror a ; 6a
- arr #$12 ; 6b 12
- jmp ($1234) ; 6c 34 12
- adc $1234 ; 6d 34 12
- ror $1234 ; 6e 34 12
- rra $1234 ; 6f 34 12
- bvs *+$14 ; 70 12
- adc ($12),y ; 71 12
- jam ; 72
- rra ($12),y ; 73 12
- nop $12,x ; 74 12
- adc $12,x ; 75 12
- ror $12,x ; 76 12
- rra $12,x ; 77 12
- sei ; 78
- adc $1234,y ; 79 34 12
- nop ; 7a
- rra $1234,y ; 7b 34 12
- nop $1234,x ; 7c 34 12
- adc $1234,x ; 7d 34 12
- ror $1234,x ; 7e 34 12
- rra $1234,x ; 7f 34 12
- nop #$12 ; 80 12
- sta ($12,x) ; 81 12
- nop #$12 ; 82 12
- sax ($12,x) ; 83 12
- sty $12 ; 84 12
- sta $12 ; 85 12
- stx $12 ; 86 12
- sax $12 ; 87 12
- dey ; 88
- nop #$12 ; 89 12
- txa ; 8a
- ane #$12 ; 8b 12
- sty $1234 ; 8c 34 12
- sta $1234 ; 8d 34 12
- stx $1234 ; 8e 34 12
- sax $1234 ; 8f 34 12
- bcc *+$14 ; 90 12
- sta ($12),y ; 91 12
- jam ; 92
- sha ($12),y ; 93 12
- sty $12,x ; 94 12
- sta $12,x ; 95 12
- stx $12,y ; 96 12
- sax $12,y ; 97 12
- tya ; 98
- sta $1234,y ; 99 34 12
- txs ; 9a
- tas $1234,y ; 9b 34 12
- shy $1234,x ; 9c 34 12
- sta $1234,x ; 9d 34 12
- shx $1234,y ; 9e 34 12
- sha $1234,y ; 9f 34 12
- ldy #$12 ; a0 12
- lda ($12,x) ; a1 12
- ldx #$12 ; a2 12
- lax ($12,x) ; a3 12
- ldy $12 ; a4 12
- lda $12 ; a5 12
- ldx $12 ; a6 12
- lax $12 ; a7 12
- tay ; a8
- lda #$12 ; a9 12
- tax ; aa
- lax #$12 ; ab 12
- ldy $1234 ; ac 34 12
- lda $1234 ; ad 34 12
- ldx $1234 ; ae 34 12
- lax $1234 ; af 34 12
- bcs *+$14 ; b0 12
- lda ($12),y ; b1 12
- jam ; b2
- lax ($12),y ; b3 12
- ldy $12,x ; b4 12
- lda $12,x ; b5 12
- ldx $12,y ; b6 12
- lax $12,y ; b7 12
- clv ; b8
- lda $1234,y ; b9 34 12
- tsx ; ba
- las $1234,y ; bb 34 12
- ldy $1234,x ; bc 34 12
- lda $1234,x ; bd 34 12
- ldx $1234,y ; be 34 12
- lax $1234,y ; bf 34 12
- cpy #$12 ; c0 12
- cmp ($12,x) ; c1 12
- nop #$12 ; c2 12
- dcp ($12,x) ; c3 12
- cpy $12 ; c4 12
- cmp $12 ; c5 12
- dec $12 ; c6 12
- dcp $12 ; c7 12
- iny ; c8
- cmp #$12 ; c9 12
- dex ; ca
- axs #$12 ; cb 12
- cpy $1234 ; cc 34 12
- cmp $1234 ; cd 34 12
- dec $1234 ; ce 34 12
- dcp $1234 ; cf 34 12
- bne *+$14 ; d0 12
- cmp ($12),y ; d1 12
- jam ; d2
- dcp ($12),y ; d3 12
- nop $12,x ; d4 12
- cmp $12,x ; d5 12
- dec $12,x ; d6 12
- dcp $12,x ; d7 12
- cld ; d8
- cmp $1234,y ; d9 34 12
- nop ; da
- dcp $1234,y ; db 34 12
- nop $1234,x ; dc 34 12
- cmp $1234,x ; dd 34 12
- dec $1234,x ; de 34 12
- dcp $1234,x ; df 34 12
- cpx #$12 ; e0 12
- sbc ($12,x) ; e1 12
- nop #$12 ; e2 12
- isc ($12,x) ; e3 12
- cpx $12 ; e4 12
- sbc $12 ; e5 12
- inc $12 ; e6 12
- isc $12 ; e7 12
- inx ; e8
- sbc #$12 ; e9 12
- nop ; ea
- sbc #$12 ; eb 12
- cpx $1234 ; ec 34 12
- sbc $1234 ; ed 34 12
- inc $1234 ; ee 34 12
- isc $1234 ; ef 34 12
- beq *+$14 ; f0 12
- sbc ($12),y ; f1 12
- jam ; f2
- isc ($12),y ; f3 12
- nop $12,x ; f4 12
- sbc $12,x ; f5 12
- inc $12,x ; f6 12
- isc $12,x ; f7 12
- sed ; f8
- sbc $1234,y ; f9 34 12
- isc $1234,y ; fb 34 12
- nop $1234,x ; fc 34 12
- sbc $1234,x ; fd 34 12
- inc $1234,x ; fe 34 12
- isc $1234,x ; ff 34 12
+++ /dev/null
-\a\12\ f4\12\1f4\12\e4\12\ 3\12\17\12\13\12'\12/4\12?4\12;4\12#\127\123\12O4\12_4\12[4\12G\12C\12W\12S\12o4\12\7f4\12{4\12g\12c\12w\12s\12Ï4\12ß4\12Û4\12Ç\12Ã\12×\12Ó\12ï4\12ÿ4\12û4\12ç\12ã\12÷\12ó\12\8f4\12\87\12\83\12\97\12¯4\12¿4\12§\12£\12³\12·\12\v\12k\12K\12Ë\12\f4\12\1c4\12\ 4\12\14\12\80\12\ 2\93\12\9f4\12\9e4\12\9c4\12\9b4\12»4\12«\12\8b\12
\ No newline at end of file
+++ /dev/null
-
- .setcpu "6502X"
-
-; all so called "illegal" opcodes. duplicated (functionally identical) ones
-; are commented out
-
-; first all totally stable undocs:
-
- slo $12 ; 07 12
- slo $1234 ; 0f 34 12
- slo $1234,x ; 1f 34 12
- slo $1234,y ; 1b 34 12
- slo ($12,x) ; 03 12
- slo $12,x ; 17 12
- slo ($12),y ; 13 12
-
- rla $12 ; 27 12
- rla $1234 ; 2f 34 12
- rla $1234,x ; 3f 34 12
- rla $1234,y ; 3b 34 12
- rla ($12,x) ; 23 12
- rla $12,x ; 37 12
- rla ($12),y ; 33 12
-
- sre $1234 ; 4f 34 12
- sre $1234,x ; 5f 34 12
- sre $1234,y ; 5b 34 12
- sre $12 ; 47 12
- sre ($12,x) ; 43 12
- sre $12,x ; 57 12
- sre ($12),y ; 53 12
-
- rra $1234 ; 6f 34 12
- rra $1234,x ; 7f 34 12
- rra $1234,y ; 7b 34 12
- rra $12 ; 67 12
- rra ($12,x) ; 63 12
- rra $12,x ; 77 12
- rra ($12),y ; 73 12
-
- dcp $1234 ; cf 34 12
- dcp $1234,x ; df 34 12
- dcp $1234,y ; db 34 12
- dcp $12 ; c7 12
- dcp ($12,x) ; c3 12
- dcp $12,x ; d7 12
- dcp ($12),y ; d3 12
-
- isc $1234 ; ef 34 12
- isc $1234,x ; ff 34 12
- isc $1234,y ; fb 34 12
- isc $12 ; e7 12
- isc ($12,x) ; e3 12
- isc $12,x ; f7 12
- isc ($12),y ; f3 12
-
- sax $1234 ; 8f 34 12
- sax $12 ; 87 12
- sax ($12,x) ; 83 12
- sax $12,y ; 97 12
-
- lax $1234 ; af 34 12
- lax $1234,y ; bf 34 12
- lax $12 ; a7 12
- lax ($12,x) ; a3 12
- lax ($12),y ; b3 12
- lax $12,y ; b7 12
-
- anc #$12 ; 0b 12
- ;anc #$12 ; 2b 12
-
- arr #$12 ; 6b 12
-
- alr #$12 ; 4b 12
-
- axs #$12 ; cb 12
-
- nop $1234 ; 0c 34 12
- nop $1234,x ; 1c 34 12
- nop $12 ; 04 12
- nop $12,x ; 14 12
- nop #$12 ; 80 12
- ;nop $1234,x ; 3c 34 12
- ;nop $1234,x ; 5c 34 12
- ;nop $1234,x ; 7c 34 12
- ;nop $1234,x ; dc 34 12
- ;nop $1234,x ; fc 34 12
- ;nop $12 ; 44 12
- ;nop $12 ; 64 12
- ;nop #$12 ; 82 12
- ;nop #$12 ; 89 12
- ;nop #$12 ; c2 12
- ;nop #$12 ; e2 12
- ;nop $12,x ; 34 12
- ;nop $12,x ; 54 12
- ;nop $12,x ; 74 12
- ;nop $12,x ; d4 12
- ;nop $12,x ; f4 12
- ;nop ; 1a
- ;nop ; 3a
- ;nop ; 5a
- ;nop ; 7a
- ;nop ; da
-
- jam ; 02
- ;jam ; 12
- ;jam ; 22
- ;jam ; 32
- ;jam ; 42
- ;jam ; 52
- ;jam ; 62
- ;jam ; 72
- ;jam ; 92
- ;jam ; b2
- ;jam ; d2
- ;jam ; f2
-
- ;sbc #$12 ; eb 12
-
-; the so-called "unstable" ones:
-
- sha ($12),y ; 93 12
- sha $1234,y ; 9f 34 12
-
- shx $1234,y ; 9e 34 12
- shy $1234,x ; 9c 34 12
-
- tas $1234,y ; 9b 34 12
- las $1234,y ; bb 34 12
-
-; the two so-called "highly unstable" ones:
-
- lax #$12 ; ab 12
-
- ane #$12 ; 8b 12
+++ /dev/null
-
- .setcpu "6502"
-
- adc $1234 ; 6d 34 12
- adc $1234,x ; 7d 34 12
- adc $1234,y ; 79 34 12
- adc $12 ; 65 12
- adc #$12 ; 69 12
- adc ($12,x) ; 61 12
- adc $12,x ; 75 12
- adc ($12),y ; 71 12
-
- and $12 ; 25 12
- and #$12 ; 29 12
- and $1234 ; 2d 34 12
- and $1234,x ; 3d 34 12
- and $1234,y ; 39 34 12
- and ($12,x) ; 21 12
- and $12,x ; 35 12
- and ($12),y ; 31 12
-
- asl $12 ; 06 12
- asl $1234 ; 0e 34 12
- asl $1234,x ; 1e 34 12
- asl $12,x ; 16 12
- asl a ; 0a
-
- bcc *+$14 ; 90 12
- bcs *+$14 ; b0 12
- beq *+$14 ; f0 12
- bmi *+$14 ; 30 12
- bne *+$14 ; d0 12
- bpl *+$14 ; 10 12
- bvc *+$14 ; 50 12
- bvs *+$14 ; 70 12
-
- bit $12 ; 24 12
- bit $1234 ; 2c 34 12
-
- brk ; 00
-
- clc ; 18
- cld ; d8
- cli ; 58
- clv ; b8
-
- cmp $1234 ; cd 34 12
- cmp $1234,x ; dd 34 12
- cmp $1234,y ; d9 34 12
- cmp $12 ; c5 12
- cmp #$12 ; c9 12
- cmp ($12,x) ; c1 12
- cmp $12,x ; d5 12
- cmp ($12),y ; d1 12
-
- cpx $1234 ; ec 34 12
- cpx #$12 ; e0 12
- cpx $12 ; e4 12
-
- cpy $1234 ; cc 34 12
- cpy #$12 ; c0 12
- cpy $12 ; c4 12
-
- dec $1234 ; ce 34 12
- dec $1234,x ; de 34 12
- dec $12 ; c6 12
- dec $12,x ; d6 12
-
- dex ; ca
- dey ; 88
-
- eor $1234 ; 4d 34 12
- eor $1234,x ; 5d 34 12
- eor $1234,y ; 59 34 12
- eor $12 ; 45 12
- eor #$12 ; 49 12
- eor ($12,x) ; 41 12
- eor $12,x ; 55 12
- eor ($12),y ; 51 12
-
- inc $1234 ; ee 34 12
- inc $1234,x ; fe 34 12
- inc $12 ; e6 12
- inc $12,x ; f6 12
-
- inx ; e8
- iny ; c8
-
- jmp $1234 ; 4c 34 12
- jmp ($1234) ; 6c 34 12
-
- jsr $1234 ; 20 34 12
-
- lda $1234 ; ad 34 12
- lda $1234,x ; bd 34 12
- lda $1234,y ; b9 34 12
- lda $12 ; a5 12
- lda #$12 ; a9 12
- lda ($12,x) ; a1 12
- lda $12,x ; b5 12
- lda ($12),y ; b1 12
-
- ldx $1234 ; ae 34 12
- ldx $1234,y ; be 34 12
- ldx #$12 ; a2 12
- ldx $12 ; a6 12
- ldx $12,y ; b6 12
-
- ldy $1234 ; ac 34 12
- ldy $1234,x ; bc 34 12
- ldy #$12 ; a0 12
- ldy $12 ; a4 12
- ldy $12,x ; b4 12
-
- lsr $1234 ; 4e 34 12
- lsr $1234,x ; 5e 34 12
- lsr $12 ; 46 12
- lsr $12,x ; 56 12
- lsr a ; 4a
-
- nop ; ea
-
- ora $12 ; 05 12
- ora #$12 ; 09 12
- ora $1234 ; 0d 34 12
- ora $1234,x ; 1d 34 12
- ora $1234,y ; 19 34 12
- ora ($12,x) ; 01 12
- ora $12,x ; 15 12
- ora ($12),y ; 11 12
-
- pha ; 48
- php ; 08
- pla ; 68
- plp ; 28
-
- rol $12 ; 26 12
- rol $1234 ; 2e 34 12
- rol $1234,x ; 3e 34 12
- rol $12,x ; 36 12
- rol a ; 2a
- ror $1234 ; 6e 34 12
- ror $1234,x ; 7e 34 12
- ror $12 ; 66 12
- ror $12,x ; 76 12
- ror a ; 6a
-
- rti ; 40
- rts ; 60
-
- sbc $1234 ; ed 34 12
- sbc $1234,x ; fd 34 12
- sbc $1234,y ; f9 34 12
- sbc $12 ; e5 12
- sbc #$12 ; e9 12
- sbc ($12,x) ; e1 12
- sbc $12,x ; f5 12
- sbc ($12),y ; f1 12
-
- sec ; 38
- sed ; f8
- sei ; 78
-
- sta $1234 ; 8d 34 12
- sta $1234,x ; 9d 34 12
- sta $1234,y ; 99 34 12
- sta $12 ; 85 12
- sta ($12,x) ; 81 12
- sta $12,x ; 95 12
- sta ($12),y ; 91 12
-
- stx $1234 ; 8e 34 12
- stx $12 ; 86 12
- stx $12,y ; 96 12
-
- sty $1234 ; 8c 34 12
- sty $12 ; 84 12
- sty $12,x ; 94 12
-
- tax ; aa
- tay ; a8
- tsx ; ba
- txa ; 8a
- txs ; 9a
- tya ; 98
--- /dev/null
+/*
+** testprogram for includes "atari_screen_charmap.h" and "atari_atascii_charmap.h"
+**
+** 19-Aug-2016, Christian Krueger
+*/
+
+#include <conio.h>
+#include <atari.h>
+#include <peekpoke.h>
+#include <string.h>
+
+
+char pcDefaultMappingString[] = "Hello Atari!";
+
+#include <atari_screen_charmap.h>
+char pcScreenMappingString[] = "Hello Atari!";
+
+#include <atari_atascii_charmap.h>
+char pcAtasciiMappingString[] = "Hello Atari!";
+
+/* THIS WON'T work due to string merging/collection problems!
+char* pcDefaultMappingString = "Hello Atari!";
+
+#include <atari_screen_charmap.h>
+char* pcScreenMappingString = "Hello Atari!";
+
+#include <atari_atascii_charmap.h>
+char* pcAtasciiMappingString = "Hello Atari!";
+*/
+
+int
+main(void)
+{
+ static unsigned char expectedAtasciiValues[] = { 40,101,108,108,111,0,33,116,97,114,105,1};
+
+ int returnValue = 0;
+ unsigned char* screen = (unsigned char*) PEEKW(88);
+
+ // check default (=atascii)
+ clrscr();
+ cputs(pcDefaultMappingString);
+ returnValue |= memcmp(screen, expectedAtasciiValues, sizeof(expectedAtasciiValues));
+
+ clrscr();
+ memcpy(screen, pcScreenMappingString, sizeof(expectedAtasciiValues));
+ returnValue |= memcmp(screen, expectedAtasciiValues, sizeof(expectedAtasciiValues));
+
+ clrscr();
+ cputs(pcAtasciiMappingString);
+ returnValue |= memcmp(screen, expectedAtasciiValues, sizeof(expectedAtasciiValues));
+
+ clrscr();
+ if (returnValue)
+ cputs("Test FAILED!");
+ else
+ cputs("Test passed.");
+
+ cputs("\n\rHit any key to exit...");
+ cgetc();
+
+ return returnValue;
+}
+
#include <stdio.h>
#include <conio.h>
#include <atari.h>
+#include <cc65.h>
extern char _defdev[];
int main(void)
{
printf("default device: %s\n", _defdev);
- if (_dos_type != SPARTADOS && _dos_type != OSADOS) cgetc();
+ if (doesclrscrafterexit()) cgetc();
return 0;
}
#include <stdlib.h>
#include <conio.h>
#include <atari.h>
+#include <cc65.h>
extern int getsp(void); /* comes from ../getsp.s */
-extern char _dos_type; /* bss variable */
unsigned char data = 0x12; /* data variable */
unsigned int *APPMHI = (unsigned int *)14; /* 14,15 */
printf(" sp: $%04X (stack ptr)\n", getsp());
if (allocmem) free(allocmem);
- if (_dos_type != 1) cgetc();
+ if (doesclrscrafterexit()) cgetc();
return(0);
}
/*
** Simple ("tiny") shell to test filename and directory functions.
-** Copyright (c) 2013, Christian Groessler, chris@groessler.org
+** Copyright (c) 2013,2016 Christian Groessler, chris@groessler.org
*/
-#define VERSION_ASC "0.90"
+#define VERSION_ASC "0.91"
#ifdef __ATARI__
#define UPPERCASE /* define (e.g. for Atari) to convert filenames etc. to upper case */
#define CHECK_SP
#endif
-#define KEYB_BUFSZ 80
+#define KEYB_BUFSZ 127
#define PROMPT ">>> "
#include <stdio.h>
#define CMD_PWD 11
#define CMD_CLS 12
#define CMD_VERBOSE 13
+#define CMD_EXEC 14
static unsigned char verbose;
static unsigned char terminate;
static unsigned char cmd;
-static unsigned char *cmd_asc, *arg1, *arg2, *arg3;
-static unsigned char keyb_buf[KEYB_BUFSZ];
+static unsigned char *cmd_asc, *arg1, *arg2, *arg3, *args; /* 'args': everything after command */
+static unsigned char keyb_buf[KEYB_BUFSZ + 1];
+static unsigned char keyb_buf2[KEYB_BUFSZ + 1];
static size_t cpbuf_sz = 4096;
struct cmd_table {
{ "mv", CMD_RENAME },
{ "ren", CMD_RENAME },
{ "pwd", CMD_PWD },
+ { "exec", CMD_EXEC },
#ifdef __ATARI__
{ "cls", CMD_CLS },
#endif
return;
}
+ /* put everything after first string into 'args' */
+
+ strcpy(keyb_buf2, keyb_buf); /* use a backup copy for 'args' */
+
+ /* skip over the first non-whitespace item */
+ cmd_asc = strtok(keyb_buf2, " \t\n");
+ if (cmd_asc)
+ args = strtok(NULL, ""); /* get everything */
+ else
+ *args = 0; /* no arguments */
+
/* split input into cmd, arg1, arg2, arg3 */
/* get and parse command */
puts("cd, chdir - change directory or drive");
puts("md, mkdir - make directory or drive");
puts("rd, rmdir - remove directory or drive");
+ puts("exec - run program");
#ifdef __ATARI__
puts("cls - clear screen");
#endif
puts("verbose - set verbosity level");
- puts("sorry, you cannot start programs here");
}
static void cmd_ls(void)
printf("rename failed: %s\n", strerror(errno));
}
+static void cmd_exec(void)
+{
+ unsigned char *progname, *arguments;
+
+ progname = strtok(args, " \t\n");
+ if (! progname) {
+ puts("usage: exec <progname> [arguments]");
+ return;
+ }
+ arguments = strtok(NULL, "");
+
+ /*printf("exec: %s %s\n", progname, arguments ? arguments : "");*/
+ (void)exec(progname, arguments);
+ printf("exec error: %s\n", strerror(errno));
+}
+
static void cmd_copy(void)
{
int srcfd = -1, dstfd = -1;
case CMD_RMDIR: cmd_rmdir(); return;
case CMD_PWD: cmd_pwd(); return;
#endif
+ case CMD_EXEC: cmd_exec(); return;
case CMD_RENAME: cmd_rename(); return;
case CMD_COPY: cmd_copy(); return;
#ifdef __ATARI__