diff --git a/Contributing.md b/Contributing.md index 74e6ead17..eb26e920b 100644 --- a/Contributing.md +++ b/Contributing.md @@ -134,7 +134,22 @@ You can refer to Annex B of the ISO C99 standard ([here](https://www.open-std.or * Hexadecimal number constants should be used except where decimal or binary numbers make much more sense in that constant's context. * Hexadecimal letters should be upper-case. * When you set two registers or two memory locations to an immediate 16-bit zero, you should use the expressions ```#<$0000``` and ```#>$0000``` (they make it obvious where you are putting the lower and upper bytes). -* If a function is declared to return a char-sized value, it actually must return an integer-sized value. (When cc65 promotes a returned value, it sometimes assumes that the value already is an integer.) +* If a function is declared to return a char-sized value, it actually must return an integer-sized value. (When cc65 promotes a returned value, it sometimes assumes that the value already is an integer.) This must be done in one of the following ways: +
+    lda #RETURN_VALUE
+    ldx #0 ; return value is char
+
+or, if the value is 0, you can use: +
+    lda #RETURN_VALUE
+    .assert RETURN_VALUE = 0
+    tax
+
+sometimes jumping to return0 could save a byte: +
+    .assert RETURN_VALUE = 0
+    jmp return 0
+
* Functions, that are intended for a platform's system library, should be optimized as much as possible. * Sometimes, there must be a trade-off between size and speed. If you think that a library function won't be used often, then you should make it small. Otherwise, you should make it fast. * Comments that are put on the right side of instructions must be aligned (start in the same character columns). diff --git a/README.md b/README.md index 697132fde..e0e2c24e7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Core team members: * [Christian Groessler](https://github.com/groessler): Atari, Atari5200, and CreatiVision library Maintainer * [dqh](https://github.com/dqh-au): GHA help * [Greg King](https://github.com/greg-king5): all around hackery -* [groepaz](https://github.com/mrdudz): CBM libary, Project Maintainer +* [groepaz](https://github.com/mrdudz): CBM library, Project Maintainer * [Oliver Schmidt](https://github.com/oliverschmidt): Apple II library Maintainer External contributors: diff --git a/asminc/cx16.inc b/asminc/cx16.inc index 1a916ecdb..be63780c8 100644 --- a/asminc/cx16.inc +++ b/asminc/cx16.inc @@ -239,12 +239,12 @@ BASIC_BUF := $0200 ; Location of command-line BASIC_BUF_LEN = 81 ; Maximum length of command-line SCREEN_PTR := $0262 ; Pointer to current row on text screen (16 bits) -STATUS := $0289 ; Status from previous I/O operation -IN_DEV := $028D ; Current input device number -OUT_DEV := $028E ; Current output device number -FNAM_LEN := $0291 ; Length of filename -SECADR := $0293 ; Secondary address -DEVNUM := $0294 ; Device number +STATUS := $0287 ; Status from previous I/O operation +IN_DEV := $028B ; Current input device number +OUT_DEV := $028C ; Current output device number +FNAM_LEN := $028F ; Length of filename +SECADR := $0291 ; Secondary address +DEVNUM := $0292 ; Device number CURS_COLOR := $0373 ; Color under the cursor CHARCOLOR := $0376 ; Cursor's color nybbles (high: background, low: foreground) RVS := $0377 ; Reverse flag @@ -258,8 +258,8 @@ LLEN := $0386 ; Line length NLINES := $0387 ; Number of screen lines ; BASIC -VARTAB := $03E2 ; Pointer to start of BASIC variables -MEMSIZE := $03EA ; Pointer to highest BASIC RAM location (+1) +VARTAB := $03E1 ; Pointer to start of BASIC variables +MEMSIZE := $03E9 ; Pointer to highest BASIC RAM location (+1) ; --------------------------------------------------------------------------- ; Vector and other locations diff --git a/asminc/kim1.inc b/asminc/kim1.inc index 68f059490..81e83b83c 100644 --- a/asminc/kim1.inc +++ b/asminc/kim1.inc @@ -15,6 +15,10 @@ OUTCHR := $1EA0 ; Output character INTCHR := $1E5A ; Input character without case conversion DUMPT := $1800 ; Dump memory to tape LOADT := $1873 ; Load memory from tape +START := $1C4F ; Enter KIM-1 monitor +SCANDS := $1F1F ; Scan 7-segment display +KEYIN := $1F40 ; Open up keyboard channel +GETKEY := $1F6A ; Return key from keyboard ; --------------------------------------------------------------------------- diff --git a/asminc/telestrat.inc b/asminc/telestrat.inc index 682696887..c57bd3de8 100644 --- a/asminc/telestrat.inc +++ b/asminc/telestrat.inc @@ -277,6 +277,8 @@ XRECLK = $3C ; Reset clock XCLCL = $3D ; Close clock XWRCLK = $3E ; Displays clock in the address in A & Y registers +XFSEEK = $3F ; Only in Orix + ; Sound primitives XSONPS = $40 ; Send data to PSG register (14 values) XOUPS = $42 ; Send Oups sound into PSG diff --git a/doc/ca65.sgml b/doc/ca65.sgml index da094359c..258808998 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -184,7 +184,7 @@ Here is a description of all the command line options: Enable an emulation feature. This is identical as using @@ -439,6 +439,15 @@ The assembler accepts command was given). +On 6502-derived platforms the + brk ; 1-byte: $00 + brk $34 ; 2-bytes: $00 $34 + brk #$34 ; 2-bytes: $00 $34 + + 65816 mode

@@ -456,6 +465,17 @@ mnemonics: TSA is an alias for TSC +The + mvn #^src, #^dst ; bank of src to bank of dst + mvn src, dst ; bank of src to bank of dst + mvp #$12, #$78 ; bank $12 to $78 + mvp $123456, $789ABC ; bank $12 to $78 + + 6502X mode

@@ -2027,7 +2047,7 @@ Here's a list of all control commands and a description, what they do: .A16

- Valid only in 65816 mode. Switch the accumulator to 16 bit. + Valid only in 65816 mode. Assume the accumulator is 16 bit. Note: This command will not emit any code, it will tell the assembler to create 16 bit operands for immediate accumulator addressing mode. @@ -2037,7 +2057,7 @@ Here's a list of all control commands and a description, what they do: .A8

- Valid only in 65816 mode. Switch the accumulator to 8 bit. + Valid only in 65816 mode. Assume the accumulator is 8 bit. Note: This command will not emit any code, it will tell the assembler to create 8 bit operands for immediate accu addressing mode. @@ -2120,15 +2140,15 @@ Here's a list of all control commands and a description, what they do: the assembler will force a segment alignment to the least common multiple of - 15, 18 and 251 - which is 22590. To protect the user against errors, the - assembler will issue a warning when the combined alignment exceeds 256. The - command line option will disable this warning. + 15, 18 and 251 - which is 22590. To protect the user against errors, when the + combined alignment is larger than the explicitly requested alignments, + the assembler will issue a warning if it also exceeds 256. The command line + option + will disable this warning. - Please note that with alignments that are a power of two (which were the - only alignments possible in older versions of the assembler), the problem is - less severe, because the least common multiple of powers to the same base is - always the larger one. + Please note that with only alignments that are a power of two, a warning will + never occur, because the least common multiple of powers to the same base is + always simply the larger one. @@ -2263,7 +2283,7 @@ See: ,,,

- Marks the end of a macro definition. + Marks the end of a macro definition. Note, .ENDMACRO should be on + its own line to successfully end the macro definition. It is possible to use + to create a symbol that references + .ENDMACRO without ending the macro definition. + + Example: + + + .macro new_mac + .define startmac .macro + .define endmac .endmacro + .endmacro + See: , , @@ -2746,15 +2778,19 @@ See: ,, + + Affects 65816 mode only. + + Allows jsr and jmp to produce long jumps if the target + address has been previously declared in a far segment, + or imported as far. + Otherwise jsl and jml must be used instead. + + Also allows to convert rts + to a long return rtl when the enclosing scope or memory model + indicates returning from a far procedure. + + This permits compatibility with the old behavior of this assembler, or other + assemblers which similarly allowed jsr and jmp to be used + this way. + loose_char_term Accept single quotes as well as double quotes as terminators for char @@ -3044,7 +3097,7 @@ See: ,

- Valid only in 65816 mode. Switch the index registers to 16 bit. + Valid only in 65816 mode. Assume the index registers are 16 bit. Note: This command will not emit any code, it will tell the assembler to create 16 bit operands for immediate operands. @@ -3055,7 +3108,7 @@ See: ,

- Valid only in 65816 mode. Switch the index registers to 8 bit. + Valid only in 65816 mode. Assume the index registers are 8 bit. Note: This command will not emit any code, it will tell the assembler to create 8 bit operands for immediate operands. @@ -3327,7 +3380,7 @@ See: ,,

- Enable output to the listing. The command must be followed by a boolean + Enable output to the listing. The command can be followed by a boolean switch ("on", "off", "+" or "-") and will enable or disable listing output. The option has no effect if the listing is not enabled by the command line @@ -3987,7 +4040,7 @@ See: ,.SMART

- Switch on or off smart mode. The command must be followed by a '+' or '-' + Switch on or off smart mode. The command can be followed by a '+' or '-' character to switch the option on or off respectively. The default is off (that is, the assembler doesn't try to be smart), but this default may be changed by the -s switch on the command line. @@ -4002,7 +4055,9 @@ See: ,In 65816 mode, replace a In 65816 mode, if the feature is enabled, + smart mode will replace a tests the rest of the line and returns true, if there are any tokens on the remainder of the line. Since @@ -4219,15 +4279,15 @@ opposite. Look at this example: -.macro ldaxy a, x, y -.ifnblank a - lda #a +.macro ldaxy i, j, k +.ifnblank i + lda #i .endif -.ifnblank x - ldx #x +.ifnblank j + ldx #j .endif -.ifnblank y - ldy #y +.ifnblank k + ldy #k .endif .endmacro diff --git a/doc/cc65-intern.sgml b/doc/cc65-intern.sgml index 8e36578b5..904cee070 100644 --- a/doc/cc65-intern.sgml +++ b/doc/cc65-intern.sgml @@ -6,7 +6,8 @@ Internal details of cc65 code generation, -such as calling assembly functions from C. +such as the expected linker configuration, +and calling assembly functions from C. @@ -16,6 +17,76 @@ such as calling assembly functions from C. +Linker configuration

+ +The C libraries and code generation depend directly on a suitable linker configuration. +There are premade configuration files in the + +Used by the C library and generated code for efficient internal and temporary state storage, +also called "pseudo-registers". + + + +Used by each platform instance of the C library in + +The default segment for generated code, and most C library code will be located here. + +Use + +Used for uninitialized variables. +Originally an acronym for "Block Started by Symbol", but the meaning of this is now obscure. + +Use + +Used for initialized variables. + +On some platforms, this may be initialized as part of the program loading process, +but on others it may have a separate + +Used for read-only (constant) data. + +Use + +This currently defines table locations for the Calling assembly functions from C

Calling conventions

diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 683249bda..1476b40a3 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -741,7 +741,7 @@ Here is a description of all the command line options: Warn about no return statement in function returning non-void. - Warn when passing structs by value. + Warn when passing structs by value. (Disabled by default.) Warn about #pragmas that aren't recognized by cc65. @@ -806,9 +806,8 @@ and the one defined by the ISO standard: The datatypes "float" and "double" are not available.

- C Functions may not return structs (or unions), and structs may not - be passed as parameters by value. However, struct assignment *is* - possible. + C Functions may pass and return structs (or unions) by value, but only + of 1, 2 or 4 byte sizes.

Most of the C library is available with only the fastcall calling convention (). It means diff --git a/doc/index.sgml b/doc/index.sgml index bfce63486..727364028 100644 --- a/doc/index.sgml +++ b/doc/index.sgml @@ -59,7 +59,7 @@ Contains hints on creating the most effective code with cc65. - Describes internal details of cc65, such as calling conventions. + Describes internal details of cc65: linker configuration, calling conventions, etc. Build programs, using the GNU Make utility. diff --git a/doc/kim1.sgml b/doc/kim1.sgml index c3494b9b9..1387d3b19 100644 --- a/doc/kim1.sgml +++ b/doc/kim1.sgml @@ -45,8 +45,10 @@ system configuration before compiling and linking user programs. The ROMs and I/O areas are defined in the configuration files, as are most of the entry points for useful subroutines in the KIM-1 monitor ROM. cc65 generated programs compiled and linked using 4k config run in the memory range of $200 - $0FFF. The 60k config expands -this range to $DFFF. The starting memory location and entry point for running the program is -$200, so when the program is transferred to the KIM-1, it is executed by typing '200 G'. +this range to $DFFF. When using the 4k config the starting memory location and entry point +for running the program is $200, so when the program is transferred to the KIM-1, it is +executed by typing '200 G'. With the 60k config the default starting memory location and entry +point is $2000. Special locations: @@ -65,7 +67,7 @@ Special locations: Platform specific header files

-Programs containing KIM-1 code may use the Loadable drivers

diff --git a/include/kim1.h b/include/kim1.h index dae246944..03c496223 100644 --- a/include/kim1.h +++ b/include/kim1.h @@ -56,5 +56,18 @@ int __fastcall__ loadt (unsigned char); /* Write to tape */ int __fastcall__ dumpt (unsigned char, const void*, const void*); -/* End of sym1.h */ + +/* Write to 7-segment LED display. Due to hardware limitations it only +** displays briefly, so must be called repeatedly to update the +** display. +**/ +void __fastcall__ scandisplay(unsigned char left, unsigned char middle, unsigned char right); + +/* +** Get a keypress from the keypad. Returns $00-$0F(0-F), $10(AD), $11(DA), $12(+), +** $13(GO), $14(PC) or $15 for no keypress. +**/ +int __fastcall__ getkey(); + +/* End of kim1.h */ #endif diff --git a/libsrc/apple2/emd/a2.auxmem.s b/libsrc/apple2/emd/a2.auxmem.s index 5ef2564b1..c582e9eec 100644 --- a/libsrc/apple2/emd/a2.auxmem.s +++ b/libsrc/apple2/emd/a2.auxmem.s @@ -73,7 +73,8 @@ INSTALL: and #$f0 cmp #$80 bne @L1 - lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + txa rts @L1: lda #EM_ERR_NO_DEVICE ; rts diff --git a/libsrc/apple2/joy/a2.stdjoy.s b/libsrc/apple2/joy/a2.stdjoy.s index 558013910..11be52eb4 100644 --- a/libsrc/apple2/joy/a2.stdjoy.s +++ b/libsrc/apple2/joy/a2.stdjoy.s @@ -71,8 +71,9 @@ INSTALL: stx gettype+2 gettype:jsr $0000 sta ostype - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; Fall through ; UNINSTALL routine. Is called before the driver is removed from memory. diff --git a/libsrc/apple2/mou/a2.stdmou.s b/libsrc/apple2/mou/a2.stdmou.s index dfc69a942..c54c09d34 100644 --- a/libsrc/apple2/mou/a2.stdmou.s +++ b/libsrc/apple2/mou/a2.stdmou.s @@ -133,8 +133,8 @@ next: inc ptr1+1 bcc :+ ; Mouse firmware not found - lda #MOUSE_ERR_NO_DEVICE + lda #MOUSE_ERR_NO_DEVICE + ldx #0 ; return value is char rts ; Check Pascal 1.1 Firmware Protocol ID bytes diff --git a/libsrc/apple2/ser/a2.ssc.s b/libsrc/apple2/ser/a2.ssc.s index d49bf3526..6ad9c3825 100644 --- a/libsrc/apple2/ser/a2.ssc.s +++ b/libsrc/apple2/ser/a2.ssc.s @@ -168,8 +168,9 @@ SER_CLOSE: sta ACIA_CMD,x ; Done, return an error code -: lda #SER_ERR_NO_DEVICE +NoDevice:lda #SER_ERR_NO_DEVICE + ldx #0 ; return value is char rts ; Invalid parameter -InvParam:lda #SER_ERR_INIT_FAILED +InvParam:lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available -InvBaud:lda #SER_ERR_BAUD_UNAVAIL +InvBaud:lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -292,8 +294,8 @@ SER_GET: : lda RecvFreeCnt ; (25) cmp #$FF bne :+ - lda #SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -336,8 +338,8 @@ SER_PUT: ; Put byte into send buffer & send : ldy SendFreeCnt bne :+ - lda #SER_ERR_OVERFLOW + lda #SER_ERR_OVERFLOW + ldx #0 ; return value is char rts : ldy SendTail @@ -346,7 +348,8 @@ SER_PUT: dec SendFreeCnt lda #$FF ; TryHard = true jsr TryToSend - lda #SER_ERR_INV_IOCTL +: lda #SER_ERR_INV_IOCTL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/atari/joy/atrmj8.s b/libsrc/atari/joy/atrmj8.s index 3a26c381d..daf11651d 100644 --- a/libsrc/atari/joy/atrmj8.s +++ b/libsrc/atari/joy/atrmj8.s @@ -69,7 +69,8 @@ INSTALL: lda #$34 sta PACTL lda #JOY_ERR_OK - ldx #0 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atari/joy/atrstd.s b/libsrc/atari/joy/atrstd.s index fd1d99d31..1a124192f 100644 --- a/libsrc/atari/joy/atrstd.s +++ b/libsrc/atari/joy/atrstd.s @@ -62,7 +62,8 @@ JOY_COUNT = 4 ; Number of joysticks we support INSTALL: lda #JOY_ERR_OK - ldx #0 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atari/mou/atrjoy.s b/libsrc/atari/mou/atrjoy.s index 3ea428576..a93c7de13 100644 --- a/libsrc/atari/mou/atrjoy.s +++ b/libsrc/atari/mou/atrjoy.s @@ -137,9 +137,10 @@ INSTALL: ldx YPos+1 jsr CMOVEY -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/atari/mou/atrst.s b/libsrc/atari/mou/atrst.s index 5d8a5cd12..626b7a8f7 100644 --- a/libsrc/atari/mou/atrst.s +++ b/libsrc/atari/mou/atrst.s @@ -268,9 +268,10 @@ INSTALL: and #$0f sta old_porta_vbi -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/atari/mou/atrtt.s b/libsrc/atari/mou/atrtt.s index 61963aa61..b1e53935e 100644 --- a/libsrc/atari/mou/atrtt.s +++ b/libsrc/atari/mou/atrtt.s @@ -132,9 +132,10 @@ INSTALL: ldx YPos+1 jsr CMOVEY -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/atari/ser/atrrdev.s b/libsrc/atari/ser/atrrdev.s index 3a7bc21c2..1d2b98e8d 100644 --- a/libsrc/atari/ser/atrrdev.s +++ b/libsrc/atari/ser/atrrdev.s @@ -135,8 +135,8 @@ my_CIOV: .code invbaud: - lda #SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char openerr: rts @@ -229,8 +229,9 @@ SER_OPEN: jsr my_CIOV bmi cioerr - lda #SER_ERR_OK +@done: lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -365,16 +367,16 @@ SER_GET: rts @nix_da:lda #SER_ERR_NO_DATA - ldx #0 + ldx #0 ; return value is char rts ser_error: lda #SER_ERR_OVERFLOW ; there is no large selection of serial error codes... :-/ - ldx #0 + ldx #0 ; return value is char rts ni_err: lda #SER_ERR_NOT_OPEN - ldx #0 + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -427,8 +429,8 @@ SER_STATUS: ; SER_IOCTL: - lda #SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -456,8 +458,8 @@ search: lda HATABS,y ; get device name ; R: device not found, return error - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atmos/joy/atmos-ijk.s b/libsrc/atmos/joy/atmos-ijk.s index 6e75a3e0b..c2bdd67ab 100644 --- a/libsrc/atmos/joy/atmos-ijk.s +++ b/libsrc/atmos/joy/atmos-ijk.s @@ -55,11 +55,12 @@ INSTALL: lda VIA::PRA and #%00100000 bne ijkPresent - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atmos/joy/atmos-pase.s b/libsrc/atmos/joy/atmos-pase.s index fd64901c9..d9982cafe 100644 --- a/libsrc/atmos/joy/atmos-pase.s +++ b/libsrc/atmos/joy/atmos-pase.s @@ -58,7 +58,8 @@ temp2: .byte $00 INSTALL: lda #JOY_ERR_OK - ldx #0 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/atmos/ser/atmos-acia.s b/libsrc/atmos/ser/atmos-acia.s index f84b66a0a..f679125d1 100644 --- a/libsrc/atmos/ser/atmos-acia.s +++ b/libsrc/atmos/ser/atmos-acia.s @@ -141,8 +141,9 @@ SER_CLOSE: sta ACIA::CMD,x ; Done, return an error code -: lda #SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -277,8 +279,8 @@ SER_PUT: ; Put byte into send buffer & send : ldy SendFreeCnt bne :+ - lda #SER_ERR_OVERFLOW + lda #SER_ERR_OVERFLOW + ldx #0 ; return value is char rts : ldy SendTail @@ -287,7 +289,8 @@ SER_PUT: dec SendFreeCnt lda #$FF ; TryHard = true jsr TryToSend - lda #SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/atmos/tgi/atmos-228-200-3.s b/libsrc/atmos/tgi/atmos-228-200-3.s index 98d2cef96..466f6922a 100644 --- a/libsrc/atmos/tgi/atmos-228-200-3.s +++ b/libsrc/atmos/tgi/atmos-228-200-3.s @@ -215,7 +215,8 @@ SETPALETTE: jsr PAPER ldy #1 jsr flipcolor - dey ; TGI_ERR_OK + .assert TGI_ERR_OK = 0, error + dey sty ERROR sty PARAM1+1 jmp INK diff --git a/libsrc/c128/emd/c128-efnram.s b/libsrc/c128/emd/c128-efnram.s index 788c73e0f..909c90048 100644 --- a/libsrc/c128/emd/c128-efnram.s +++ b/libsrc/c128/emd/c128-efnram.s @@ -87,16 +87,17 @@ INSTALL: cli cmp tmp1 beq @ram_present - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @ram_present: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page + .assert EM_ERR_OK = 0, error inx - txa ; A = X = EM_ERR_OK + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-georam.s b/libsrc/c128/emd/c128-georam.s index 7511c6841..ecf12f6cd 100644 --- a/libsrc/c128/emd/c128-georam.s +++ b/libsrc/c128/emd/c128-georam.s @@ -120,16 +120,16 @@ INSTALL: bne @setok @notpresent: - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @setok: lda #0 sta pagecount stx pagecount+1 - lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts check: diff --git a/libsrc/c128/emd/c128-ifnram.s b/libsrc/c128/emd/c128-ifnram.s index 01a4fdf8e..c51b775b2 100644 --- a/libsrc/c128/emd/c128-ifnram.s +++ b/libsrc/c128/emd/c128-ifnram.s @@ -87,16 +87,17 @@ INSTALL: cli cmp tmp1 beq @ram_present - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @ram_present: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page + .assert EM_ERR_OK = 0, error inx - txa ; A = X = EM_ERR_OK + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-ram.s b/libsrc/c128/emd/c128-ram.s index 3fc52c9cc..0ae504b84 100644 --- a/libsrc/c128/emd/c128-ram.s +++ b/libsrc/c128/emd/c128-ram.s @@ -68,8 +68,9 @@ INSTALL: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page + .assert EM_ERR_OK = 0, error inx - txa ; A = X = EM_ERR_OK + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-ram2.s b/libsrc/c128/emd/c128-ram2.s index 7d2703fa5..92e72700a 100644 --- a/libsrc/c128/emd/c128-ram2.s +++ b/libsrc/c128/emd/c128-ram2.s @@ -107,8 +107,9 @@ INSTALL: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page + .assert EM_ERR_OK = 0, error inx - txa ; A = X = EM_ERR_OK + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-ramcart.s b/libsrc/c128/emd/c128-ramcart.s index e72d053ac..c58c1cd1b 100644 --- a/libsrc/c128/emd/c128-ramcart.s +++ b/libsrc/c128/emd/c128-ramcart.s @@ -97,13 +97,14 @@ INSTALL: lda #0 sta pagecount stx pagecount+1 - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts @notpresent: @readonly: - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/emd/c128-reu.s b/libsrc/c128/emd/c128-reu.s index 84e7cb695..8228a0517 100644 --- a/libsrc/c128/emd/c128-reu.s +++ b/libsrc/c128/emd/c128-reu.s @@ -126,8 +126,9 @@ size_found: pagecount_ok: stx pagecount sty pagecount+1 - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts ; common REU setup for size check diff --git a/libsrc/c128/emd/c128-vdc.s b/libsrc/c128/emd/c128-vdc.s index accb82154..8d0b77fd2 100644 --- a/libsrc/c128/emd/c128-vdc.s +++ b/libsrc/c128/emd/c128-vdc.s @@ -121,8 +121,9 @@ INSTALL: lda vdc_cset_save jsr vdcputreg @keep64kBit: - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts test64k: diff --git a/libsrc/c128/joy/c128-ptvjoy.s b/libsrc/c128/joy/c128-ptvjoy.s index 180f7667d..0a1c53587 100644 --- a/libsrc/c128/joy/c128-ptvjoy.s +++ b/libsrc/c128/joy/c128-ptvjoy.s @@ -53,8 +53,9 @@ JOY_COUNT = 4 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/joy/c128-stdjoy.s b/libsrc/c128/joy/c128-stdjoy.s index bf2e2fea7..ee04374ee 100644 --- a/libsrc/c128/joy/c128-stdjoy.s +++ b/libsrc/c128/joy/c128-stdjoy.s @@ -57,8 +57,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c128/mou/c128-1351.s b/libsrc/c128/mou/c128-1351.s index 79ccbe0de..76e28d9f7 100644 --- a/libsrc/c128/mou/c128-1351.s +++ b/libsrc/c128/mou/c128-1351.s @@ -194,9 +194,10 @@ INSTALL: sta (ptr3),y cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/c128/mou/c128-inkwell.s b/libsrc/c128/mou/c128-inkwell.s index b8e71bbb1..2aac7d32d 100644 --- a/libsrc/c128/mou/c128-inkwell.s +++ b/libsrc/c128/mou/c128-inkwell.s @@ -228,9 +228,10 @@ INSTALL: jsr MoveX cli -; Done, return zero. +; Done lda #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error tax rts diff --git a/libsrc/c128/mou/c128-joy.s b/libsrc/c128/mou/c128-joy.s index 065674dc0..d809db526 100644 --- a/libsrc/c128/mou/c128-joy.s +++ b/libsrc/c128/mou/c128-joy.s @@ -195,9 +195,10 @@ INSTALL: sta (ptr3),y cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/c128/mou/c128-pot.s b/libsrc/c128/mou/c128-pot.s index e582d64fb..1cbe4aa18 100644 --- a/libsrc/c128/mou/c128-pot.s +++ b/libsrc/c128/mou/c128-pot.s @@ -195,9 +195,10 @@ INSTALL: sta (ptr3),y cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts diff --git a/libsrc/c128/ser/c128-swlink.s b/libsrc/c128/ser/c128-swlink.s index 3337e2668..7d36eb5bc 100644 --- a/libsrc/c128/ser/c128-swlink.s +++ b/libsrc/c128/ser/c128-swlink.s @@ -187,8 +187,9 @@ SetNMI: sta NMIVec ; Done, return an error code - lda #SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -300,8 +302,9 @@ SER_CLOSE: ; Return OK - lda #SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -370,7 +373,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c16/emd/c16-ram.s b/libsrc/c16/emd/c16-ram.s index a8083aca4..937019974 100644 --- a/libsrc/c16/emd/c16-ram.s +++ b/libsrc/c16/emd/c16-ram.s @@ -77,12 +77,13 @@ INSTALL: ldx #$FF stx curpage ; Invalidate the current page - inx ; X = 0 - txa ; A = X = EM_ERR_OK + .assert EM_ERR_OK = 0, error + inx + txa rts -nomem: ldx #>EM_ERR_NO_DEVICE - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts @not_present: cli - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/emd/c64-c256k.s b/libsrc/c64/emd/c64-c256k.s index 79706e8fb..5a4bc54c3 100644 --- a/libsrc/c64/emd/c64-c256k.s +++ b/libsrc/c64/emd/c64-c256k.s @@ -158,13 +158,14 @@ INSTALL: jsr restore_data cpy #$01 beq @present - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @present: - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-dqbb.s b/libsrc/c64/emd/c64-dqbb.s index 986c5939d..6a63b3baa 100644 --- a/libsrc/c64/emd/c64-dqbb.s +++ b/libsrc/c64/emd/c64-dqbb.s @@ -147,13 +147,14 @@ INSTALL: jsr restore_data cpy #$01 beq @present - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @present: - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-georam.s b/libsrc/c64/emd/c64-georam.s index 97f1a7cc4..0116fe8ea 100644 --- a/libsrc/c64/emd/c64-georam.s +++ b/libsrc/c64/emd/c64-georam.s @@ -121,16 +121,17 @@ INSTALL: bne @setok @notpresent: - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + .assert EM_ERR_OK = 0, error + tax rts @setok: lda #0 sta pagecount stx pagecount+1 - lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts check: diff --git a/libsrc/c64/emd/c64-isepic.s b/libsrc/c64/emd/c64-isepic.s index 3764443e2..2b7949757 100644 --- a/libsrc/c64/emd/c64-isepic.s +++ b/libsrc/c64/emd/c64-isepic.s @@ -76,13 +76,14 @@ INSTALL: beq @setok @notpresent: - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @setok: - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-kerberos.s b/libsrc/c64/emd/c64-kerberos.s index 30183362f..20be4e409 100644 --- a/libsrc/c64/emd/c64-kerberos.s +++ b/libsrc/c64/emd/c64-kerberos.s @@ -82,13 +82,14 @@ INSTALL: cmp #$AA bne @notpresent - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts @notpresent: - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char ; use rts from UNINSTALL below ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-ram.s b/libsrc/c64/emd/c64-ram.s index 5355b552d..cdd7b8965 100644 --- a/libsrc/c64/emd/c64-ram.s +++ b/libsrc/c64/emd/c64-ram.s @@ -65,8 +65,9 @@ window: .res 256 ; Memory "window" INSTALL: ldx #$FF stx curpage ; Invalidate the current page - inx ; X = 0 - txa ; A = X = EM_ERR_OK + .assert EM_ERR_OK = 0, error + inx + txa ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-ramcart.s b/libsrc/c64/emd/c64-ramcart.s index 8998bb6d6..a99f25b4f 100644 --- a/libsrc/c64/emd/c64-ramcart.s +++ b/libsrc/c64/emd/c64-ramcart.s @@ -98,13 +98,13 @@ INSTALL: lda #0 sta pagecount stx pagecount+1 - lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts @notpresent: @readonly: - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-reu.s b/libsrc/c64/emd/c64-reu.s index 07ac1fbed..832e66f51 100644 --- a/libsrc/c64/emd/c64-reu.s +++ b/libsrc/c64/emd/c64-reu.s @@ -127,8 +127,9 @@ size_found: pagecount_ok: stx pagecount sty pagecount+1 - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts ; common REU setup for size check @@ -152,6 +153,7 @@ reu_size_check_common: nodevice: lda #EM_ERR_NO_DEVICE + .assert EM_ERR_OK = 0, error ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/emd/c64-vdc.s b/libsrc/c64/emd/c64-vdc.s index 2448f09d4..60fbccbbf 100644 --- a/libsrc/c64/emd/c64-vdc.s +++ b/libsrc/c64/emd/c64-vdc.s @@ -87,8 +87,8 @@ INSTALL: bne @L0 iny bne @L0 - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE +; ldx #0 ; return value is char rts @present: @@ -131,8 +131,9 @@ INSTALL: sta pagecount stx pagecount+1 @endok: - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts test64k: diff --git a/libsrc/c64/emd/dtv-himem.s b/libsrc/c64/emd/dtv-himem.s index 6dde874f7..4d19b19d5 100644 --- a/libsrc/c64/emd/dtv-himem.s +++ b/libsrc/c64/emd/dtv-himem.s @@ -93,15 +93,16 @@ INSTALL: ; DTV not found - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @present: ldx #$FF stx curpage+1 ; Invalidate curpage - inx ; X = 0 - txa ; A/X = EM_ERR_OK + .assert EM_ERR_OK = 0, error + inx + txa ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/joy/c64-hitjoy.s b/libsrc/c64/joy/c64-hitjoy.s index 3b4a0b909..a9d454fd0 100644 --- a/libsrc/c64/joy/c64-hitjoy.s +++ b/libsrc/c64/joy/c64-hitjoy.s @@ -59,8 +59,9 @@ temp4: .byte 0 ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/joy/c64-numpad.s b/libsrc/c64/joy/c64-numpad.s index 0ccdc4fcd..f6839d6cf 100644 --- a/libsrc/c64/joy/c64-numpad.s +++ b/libsrc/c64/joy/c64-numpad.s @@ -100,12 +100,14 @@ masktable: ; INSTALL: - lda #JOY_ERR_OK ; Assume we have a joystick - ldx VIC_CLK_128 ; Test for a C128 - cpx #$FF + lda #JOY_ERR_OK ; Assume we have a "joystick" + .assert JOY_ERR_OK = 0, error + tax ; Set high byte + ldy VIC_CLK_128 ; Test for a C128 + cpy #$FF bne @C128 ; Jump if we have one lda #JOY_ERR_NO_DEVICE ; No C128 -> no numpad -@C128: ldx #0 ; Set high byte +@C128: ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/joy/c64-ptvjoy.s b/libsrc/c64/joy/c64-ptvjoy.s index a772fb5f6..30466b2c2 100644 --- a/libsrc/c64/joy/c64-ptvjoy.s +++ b/libsrc/c64/joy/c64-ptvjoy.s @@ -52,8 +52,9 @@ JOY_COUNT = 4 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/c64/joy/c64-stdjoy.s b/libsrc/c64/joy/c64-stdjoy.s index d11093fba..511032507 100644 --- a/libsrc/c64/joy/c64-stdjoy.s +++ b/libsrc/c64/joy/c64-stdjoy.s @@ -56,8 +56,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/c64/mou/c64-1351.s b/libsrc/c64/mou/c64-1351.s index a7d042c7b..ce0f18803 100644 --- a/libsrc/c64/mou/c64-1351.s +++ b/libsrc/c64/mou/c64-1351.s @@ -152,9 +152,10 @@ INSTALL: jsr CMOVEY cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -307,8 +308,8 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c64/mou/c64-inkwell.s b/libsrc/c64/mou/c64-inkwell.s index 9c876a7c8..d2f14a6f0 100644 --- a/libsrc/c64/mou/c64-inkwell.s +++ b/libsrc/c64/mou/c64-inkwell.s @@ -168,6 +168,7 @@ INSTALL: ; Done, return zero. lda #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error tax rts @@ -319,8 +320,8 @@ INFO: jsr POS ; Must return an error code in .XA. ; -IOCTL: lda #MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c64/mou/c64-joy.s b/libsrc/c64/mou/c64-joy.s index f2a501000..5ee1b4f84 100644 --- a/libsrc/c64/mou/c64-joy.s +++ b/libsrc/c64/mou/c64-joy.s @@ -156,9 +156,10 @@ INSTALL: jsr CMOVEY cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -312,8 +313,8 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c64/mou/c64-pot.s b/libsrc/c64/mou/c64-pot.s index 102ca351c..9bdf24f62 100644 --- a/libsrc/c64/mou/c64-pot.s +++ b/libsrc/c64/mou/c64-pot.s @@ -139,9 +139,10 @@ INSTALL: jsr CMOVEY cli -; Done, return zero (= MOUSE_ERR_OK) +; Done - ldx #$00 + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -297,8 +298,8 @@ INFO: jsr POS ; Must return an error code in a/x. ; -IOCTL: lda #MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/c64/ser/c64-swlink.s b/libsrc/c64/ser/c64-swlink.s index 597cf1dd6..81c9916a6 100644 --- a/libsrc/c64/ser/c64-swlink.s +++ b/libsrc/c64/ser/c64-swlink.s @@ -161,8 +161,9 @@ SetNMI: sta NMIVec ; Done, return an error code - lda #SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -274,8 +276,9 @@ SER_CLOSE: ; Return OK - lda #SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -344,7 +347,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/cbm510/emd/cbm510-ram.s b/libsrc/cbm510/emd/cbm510-ram.s index f724c7360..6cc319b7f 100644 --- a/libsrc/cbm510/emd/cbm510-ram.s +++ b/libsrc/cbm510/emd/cbm510-ram.s @@ -81,8 +81,9 @@ INSTALL: sbc #$00 sta pagecount -@L1: lda #EM_ERR_OK +@L1: lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/cbm510/joy/cbm510-std.s b/libsrc/cbm510/joy/cbm510-std.s index 4e47fc1a0..f7cbb2cdc 100644 --- a/libsrc/cbm510/joy/cbm510-std.s +++ b/libsrc/cbm510/joy/cbm510-std.s @@ -57,8 +57,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/cbm510/mou/cbm510-inkwl.s b/libsrc/cbm510/mou/cbm510-inkwl.s index 91bc52fcd..ea6d95934 100644 --- a/libsrc/cbm510/mou/cbm510-inkwl.s +++ b/libsrc/cbm510/mou/cbm510-inkwl.s @@ -175,6 +175,7 @@ INSTALL: ; Done, return zero. lda #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error tax rts @@ -331,8 +332,8 @@ INFO: jsr POS ; Must return an error code in .XA. ; -IOCTL: lda #MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/cbm510/mou/cbm510-joy.s b/libsrc/cbm510/mou/cbm510-joy.s index 8aa3a778e..4daa49272 100644 --- a/libsrc/cbm510/mou/cbm510-joy.s +++ b/libsrc/cbm510/mou/cbm510-joy.s @@ -140,7 +140,8 @@ INSTALL: ; Done, return zero. - ldx #>MOUSE_ERR_OK + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -315,8 +316,8 @@ POS: ldy #MOUSE_POS::XCOORD ; Structure offset ; Must return an error code in .XA. ; -IOCTL: lda #MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/cbm510/ser/cbm510-std.s b/libsrc/cbm510/ser/cbm510-std.s index 64f613cd5..cc58c1233 100644 --- a/libsrc/cbm510/ser/cbm510-std.s +++ b/libsrc/cbm510/ser/cbm510-std.s @@ -148,8 +148,9 @@ SER_CLOSE: ; Done, return an error code - lda #SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -253,8 +255,8 @@ SER_GET: @L1: lda RecvFreeCnt cmp #$ff bne @L2 - lda #SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -301,7 +303,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/cbm610/emd/cbm610-ram.s b/libsrc/cbm610/emd/cbm610-ram.s index 5c67df7a4..5aa43b0c2 100644 --- a/libsrc/cbm610/emd/cbm610-ram.s +++ b/libsrc/cbm610/emd/cbm610-ram.s @@ -81,8 +81,9 @@ INSTALL: sbc #$00 sta pagecount -@L1: lda #EM_ERR_OK +@L1: lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/cbm610/ser/cbm610-std.s b/libsrc/cbm610/ser/cbm610-std.s index 7cdb285bd..f7ddde935 100644 --- a/libsrc/cbm610/ser/cbm610-std.s +++ b/libsrc/cbm610/ser/cbm610-std.s @@ -149,8 +149,9 @@ SER_CLOSE: ; Done, return an error code - lda #SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -254,8 +256,8 @@ SER_GET: @L1: lda RecvFreeCnt cmp #$ff bne @L2 - lda #SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -302,7 +304,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/common/_printf.s b/libsrc/common/_printf.s index 840d42127..a0074583e 100644 --- a/libsrc/common/_printf.s +++ b/libsrc/common/_printf.s @@ -502,10 +502,10 @@ DoFormat: ; It is a character jsr GetIntArg ; Get the argument (promoted to int) - sta Buf ; Place it as zero terminated string... - lda #0 - sta Buf+1 ; ...into the buffer - jmp HaveArg ; Done + sta Buf ; Place it into the buffer + ldx #0 + lda #1 ; Buffer length is 1 + jmp HaveArg1 ; Is it an integer? @@ -671,6 +671,7 @@ HaveArg: lda Str ldx Str+1 jsr _strlen ; Get length of argument +HaveArg1: ; Jumped into here from %c handling sta ArgLen stx ArgLen+1 diff --git a/libsrc/creativision/joy/creativision-stdjoy.s b/libsrc/creativision/joy/creativision-stdjoy.s index 73b0c249f..43f9a2b40 100644 --- a/libsrc/creativision/joy/creativision-stdjoy.s +++ b/libsrc/creativision/joy/creativision-stdjoy.s @@ -59,7 +59,8 @@ JOY_RIGHT = $08 ; INSTALL: lda #JOY_ERR_OK - ldx #>$0000 + .assert JOY_ERR_OK = 0, error + tax ; rts ; Fall through ; ------------------------------------------------------------------------ diff --git a/libsrc/cx16/joy/cx16-std.s b/libsrc/cx16/joy/cx16-std.s index a40fcb061..5def55511 100644 --- a/libsrc/cx16/joy/cx16-std.s +++ b/libsrc/cx16/joy/cx16-std.s @@ -55,8 +55,9 @@ JOY_COUNT = $05 ; Number of joysticks we support ; Must return a JOY_ERR_xx code in .XA . INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/cx16/mou/cx16-std.s b/libsrc/cx16/mou/cx16-std.s index 3af7d2eb3..f211815de 100644 --- a/libsrc/cx16/mou/cx16-std.s +++ b/libsrc/cx16/mou/cx16-std.s @@ -139,7 +139,8 @@ INSTALL: ; Done, return zero - ldx #>MOUSE_ERR_OK + ldx #MOUSE_ERR_OK + .assert MOUSE_ERR_OK = 0, error txa rts @@ -300,8 +301,8 @@ INFO: jsr BUTTONS ; Will not touch ptr1 ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in .XA . -IOCTL: lda #MOUSE_ERR_INV_IOCTL +IOCTL: lda #MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now + ldx #0 ; return value is char ; rts ; Fall through ;---------------------------------------------------------------------------- diff --git a/libsrc/gamate/joy/gamate-stdjoy.s b/libsrc/gamate/joy/gamate-stdjoy.s index 8f927cdf5..514f92db4 100644 --- a/libsrc/gamate/joy/gamate-stdjoy.s +++ b/libsrc/gamate/joy/gamate-stdjoy.s @@ -47,8 +47,9 @@ JOY_COUNT = 1 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/geos-cbm/emd/geos-vdc.s b/libsrc/geos-cbm/emd/geos-vdc.s index 27316e1a0..2e7d19c03 100644 --- a/libsrc/geos-cbm/emd/geos-vdc.s +++ b/libsrc/geos-cbm/emd/geos-vdc.s @@ -125,8 +125,9 @@ INSTALL: pla sta $01 plp - lda #EM_ERR_OK + lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts test64k: diff --git a/libsrc/geos-cbm/joy/geos-stdjoy.s b/libsrc/geos-cbm/joy/geos-stdjoy.s index 2787cb594..a3fd4ffc8 100644 --- a/libsrc/geos-cbm/joy/geos-stdjoy.s +++ b/libsrc/geos-cbm/joy/geos-stdjoy.s @@ -53,8 +53,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/joystick/joy_unload.s b/libsrc/joystick/joy_unload.s index 25d54ff02..f52b7a2c1 100644 --- a/libsrc/joystick/joy_unload.s +++ b/libsrc/joystick/joy_unload.s @@ -10,7 +10,7 @@ .include "modload.inc" .import joy_clear_ptr - .import return0 + .import return0, return1 @@ -31,7 +31,6 @@ _joy_unload: jmp return0 ; Return JOY_ERR_OK no_driver: - tax ; X = 0 pla ; Remove pushed junk - lda #JOY_ERR_NO_DRIVER - rts + .assert JOY_ERR_NO_DRIVER = 1, error + jmp return1 ; Return JOY_ERR_NO_DRIVER diff --git a/libsrc/kim1/crt0.s b/libsrc/kim1/crt0.s index f1fee86c1..906b3b980 100644 --- a/libsrc/kim1/crt0.s +++ b/libsrc/kim1/crt0.s @@ -40,8 +40,6 @@ _init: cld ; Clear decimal mode jsr _main -; Back from main (this is also the _exit entry). There may be a more elegant way to -; return to the monitor on the KIM-1, but I don't know it! - -_exit: brk +; Back from main (this is also the _exit entry). Jumps to the KIM-1 monitor. +_exit: jmp START diff --git a/libsrc/kim1/getkey.s b/libsrc/kim1/getkey.s new file mode 100644 index 000000000..b36cd4b4c --- /dev/null +++ b/libsrc/kim1/getkey.s @@ -0,0 +1,18 @@ +; +; int __fastcall__ getkey(); +; + +.include "kim1.inc" + +.import popa + +.export _getkey + +.proc _getkey + + jsr KEYIN ; Open up keyboard channel + jsr GETKEY ; Get key code + ldx #0 ; MSB of return value is zero + rts + +.endproc diff --git a/libsrc/kim1/read.s b/libsrc/kim1/read.s index 5566a9f27..dd178ee98 100644 --- a/libsrc/kim1/read.s +++ b/libsrc/kim1/read.s @@ -27,15 +27,10 @@ begin: dec ptr2 beq done ; If buffer full, return getch: jsr INTCHR ; Get character using Monitor ROM call - ;jsr OUTCHR ; Echo it and #$7F ; Clear top bit - cmp #$07 ; Check for '\a' - bne chkcr ; ...if BEL character - ;jsr BEEP ; Make beep sound TODO -chkcr: cmp #$0D ; Check for '\r' + cmp #$0D ; Check for '\r' bne putch ; ...if CR character lda #$0A ; Replace with '\n' - jsr OUTCHR ; and echo it putch: ldy #$00 ; Put char into return buffer sta (ptr1),y diff --git a/libsrc/kim1/scandisplay.s b/libsrc/kim1/scandisplay.s new file mode 100644 index 000000000..0f46a5de4 --- /dev/null +++ b/libsrc/kim1/scandisplay.s @@ -0,0 +1,21 @@ +; +; void __fastcall__ scandisplay(unsigned char left, unsigned char middle, unsigned char right); +; + +.include "kim1.inc" + +.import popa + +.export _scandisplay + +.proc _scandisplay + + sta $F9 ; Rightmost display data + jsr popa + sta $FA ; Middle display data + jsr popa + sta $FB ; Leftmost display data + jsr SCANDS + rts + +.endproc diff --git a/libsrc/kim1/write.s b/libsrc/kim1/write.s index 216f5031c..96bcc91d1 100644 --- a/libsrc/kim1/write.s +++ b/libsrc/kim1/write.s @@ -28,11 +28,10 @@ begin: dec ptr2 outch: ldy #0 lda (ptr1),y + pha ; Save A (changed by OUTCHR) jsr OUTCHR ; Send character using Monitor call - cmp #$07 ; Check for '\a' - bne chklf ; ...if BEL character -;jsr BEEP ; Make beep sound -chklf: cmp #$0A ; Check for 'n' + pla ; Restore A + cmp #$0A ; Check for '\n' bne next ; ...if LF character lda #$0D ; Add a carriage return jsr OUTCHR diff --git a/libsrc/lynx/joy/lynx-stdjoy.s b/libsrc/lynx/joy/lynx-stdjoy.s index c81a97dbf..45eb8ab4e 100644 --- a/libsrc/lynx/joy/lynx-stdjoy.s +++ b/libsrc/lynx/joy/lynx-stdjoy.s @@ -58,8 +58,9 @@ JOY_COUNT = 1 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/lynx/ser/lynx-comlynx.s b/libsrc/lynx/ser/lynx-comlynx.s index ded862eaa..8aa3c838e 100644 --- a/libsrc/lynx/ser/lynx-comlynx.s +++ b/libsrc/lynx/ser/lynx-comlynx.s @@ -75,8 +75,9 @@ SER_UNINSTALL: SER_CLOSE: ; Disable interrupts ; Done, return an error code - lda #SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts ;---------------------------------------------------------------------------- @@ -190,8 +191,8 @@ SER_OPEN: cmp #SER_BAUD_134_5 beq setbaudrate - lda #SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts setprescaler: stx TIM4CTLA @@ -238,12 +239,13 @@ checkhs: lda contrl ora #RxIntEnable|ResetErr sta SERCTL - lda #SER_ERR_OK + lda #SER_ERR_OK + .assert SER_ERR_OK = 0, error + tax rts invparameter: - lda #SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -255,8 +257,8 @@ SER_GET: lda RxPtrIn cmp RxPtrOut bne GetByte - lda #SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts GetByte: ldy RxPtrOut @@ -277,8 +279,8 @@ SER_PUT: ina cmp TxPtrOut bne PutByte - lda #SER_ERR_OVERFLOW + lda #SER_ERR_OVERFLOW + ldx #0 ; return value is char rts PutByte: ldy TxPtrIn @@ -296,7 +298,8 @@ PutByte: sta TxDone plp @L1: - lda #SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- diff --git a/libsrc/mouse/mouse_unload.s b/libsrc/mouse/mouse_unload.s index 8c9018484..ecd7846ab 100644 --- a/libsrc/mouse/mouse_unload.s +++ b/libsrc/mouse/mouse_unload.s @@ -8,7 +8,7 @@ .include "mouse-kernel.inc" .include "modload.inc" - .import return0 + .import return0, return1 @@ -29,7 +29,6 @@ _mouse_unload: jmp return0 ; Return MOUSE_ERR_OK no_driver: - tax ; X = 0 pla ; Remove pushed junk - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/pet/joy/pet-ptvjoy.s b/libsrc/pet/joy/pet-ptvjoy.s index c098072fb..ee14c95c8 100644 --- a/libsrc/pet/joy/pet-ptvjoy.s +++ b/libsrc/pet/joy/pet-ptvjoy.s @@ -51,8 +51,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/plus4/joy/plus4-stdjoy.s b/libsrc/plus4/joy/plus4-stdjoy.s index e8e85fedc..86f080dae 100644 --- a/libsrc/plus4/joy/plus4-stdjoy.s +++ b/libsrc/plus4/joy/plus4-stdjoy.s @@ -58,8 +58,9 @@ JOY_COUNT = 2 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/plus4/ser/plus4-stdser.s b/libsrc/plus4/ser/plus4-stdser.s index bb44a4cf9..fbdc61b2e 100644 --- a/libsrc/plus4/ser/plus4-stdser.s +++ b/libsrc/plus4/ser/plus4-stdser.s @@ -157,8 +157,9 @@ SER_CLOSE: ; Done, return an error code - lda #SER_ERR_INIT_FAILED + lda #SER_ERR_INIT_FAILED + ldx #0 ; return value is char rts ; Baud rate not available InvBaud: - lda #SER_ERR_BAUD_UNAVAIL + lda #SER_ERR_BAUD_UNAVAIL + ldx #0 ; return value is char rts ;---------------------------------------------------------------------------- @@ -261,8 +263,8 @@ SER_GET: @L1: lda RecvFreeCnt ; (25) cmp #$ff bne @L2 - lda #SER_ERR_NO_DATA + lda #SER_ERR_NO_DATA + ldx #0 ; return value is char rts ; Check for flow stopped & enough free: release flow control @@ -309,7 +311,7 @@ SER_PUT: @L2: ldx SendFreeCnt bne @L3 - lda #SER_ERR_INV_IOCTL + lda #SER_ERR_INV_IOCTL ; We don't support ioclts for now + ldx #0 ; return value is char rts ; Run into IRQ instead ;---------------------------------------------------------------------------- diff --git a/libsrc/serial/ser_unload.s b/libsrc/serial/ser_unload.s index bf7201255..7cd0f7125 100644 --- a/libsrc/serial/ser_unload.s +++ b/libsrc/serial/ser_unload.s @@ -10,7 +10,7 @@ .include "modload.inc" .import ser_clear_ptr - .import return0 + .import return0, return1 @@ -28,10 +28,10 @@ _ser_unload: tax pla ; Get pointer to driver jsr _mod_free ; Free the driver - jmp return0 ; Return SER_ERR_OK + .assert SER_ERR_OK = 0, error + jmp return0 no_driver: - tax ; X = 0 pla ; Remove pushed junk - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead diff --git a/libsrc/telestrat/joy/telestrat.s b/libsrc/telestrat/joy/telestrat.s index 0f5d28651..7472ab187 100644 --- a/libsrc/telestrat/joy/telestrat.s +++ b/libsrc/telestrat/joy/telestrat.s @@ -54,8 +54,9 @@ INSTALL: sta VIA2::PRB ; We could detect joysticks because with previous command bit0,1,2,3,4 should be set to 1 after ; But if some one press fire or press direction, we could reach others values which could break joystick detection. - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/telestrat/lseek.s b/libsrc/telestrat/lseek.s new file mode 100644 index 000000000..11d1fad33 --- /dev/null +++ b/libsrc/telestrat/lseek.s @@ -0,0 +1,39 @@ +; +; Jede (jede@oric.org), 2023-03-13 +; + +; off_t __fastcall__ lseek(int fd, off_t offset, int whence); + + .export _lseek + + .include "telestrat.inc" + .include "zeropage.inc" + + .import popax + +.proc _lseek + ; Save whence + sta tmp1 + ; Skip X + + ; Get offset and store + + jsr popax + sta tmp2 + stx tmp3 + + jsr popax + sta RESB + stx RESB+1 + + ; Get FD + jsr popax + ; Does not need X + sta RES ; Save FD + + lda tmp2 + ldy tmp3 + ldx tmp1 ; Get whence + BRK_TELEMON XFSEEK + rts +.endproc diff --git a/libsrc/vic20/emd/vic20-georam.s b/libsrc/vic20/emd/vic20-georam.s index a960e9a1a..4e3121c05 100644 --- a/libsrc/vic20/emd/vic20-georam.s +++ b/libsrc/vic20/emd/vic20-georam.s @@ -119,16 +119,16 @@ INSTALL: bne @setok @notpresent: - lda #EM_ERR_NO_DEVICE + lda #EM_ERR_NO_DEVICE + ldx #0 ; return value is char rts @setok: lda #0 sta pagecount stx pagecount+1 - lda #EM_ERR_OK + .assert EM_ERR_OK = 0, error + tax rts check: diff --git a/libsrc/vic20/emd/vic20-rama.s b/libsrc/vic20/emd/vic20-rama.s index 133c3974b..4264e2caf 100644 --- a/libsrc/vic20/emd/vic20-rama.s +++ b/libsrc/vic20/emd/vic20-rama.s @@ -71,12 +71,13 @@ INSTALL: ldx #$FF stx curpage ; Invalidate the current page - inx ; X = 0 - txa ; A = X = EM_ERR_OK + .assert EM_ERR_OK = 0, error + inx + txa rts -nomem: ldx #>EM_ERR_NO_DEVICE - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/libsrc/vic20/joy/vic20-stdjoy.s b/libsrc/vic20/joy/vic20-stdjoy.s index ee8dc93d7..b3de8766c 100644 --- a/libsrc/vic20/joy/vic20-stdjoy.s +++ b/libsrc/vic20/joy/vic20-stdjoy.s @@ -57,8 +57,9 @@ JOY_COUNT = 1 ; Number of joysticks we support ; INSTALL: - lda #JOY_ERR_OK + lda #JOY_ERR_OK + .assert JOY_ERR_OK = 0, error + tax ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ diff --git a/samples/kim1/kimKeyDisp.c b/samples/kim1/kimKeyDisp.c new file mode 100644 index 000000000..63839d19e --- /dev/null +++ b/samples/kim1/kimKeyDisp.c @@ -0,0 +1,52 @@ +/* Example illustrating scandisplay() and getkey() functions. */ + +#include +#include + +int main (void) +{ + int i, j, k, l; + int last = 15; + + printf("\nKIM-1 Demo\n"); + + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + for (k = 0; k < 16; k++) { + scandisplay(i, j, k); + + l = getkey(); + + if (l != last) { + switch (l) { + case 0x0: case 0x1: case 0x2: case 0x3: + case 0x4: case 0x5: case 0x6: case 0x7: + case 0x8: case 0x9: case 0xa: case 0xb: + case 0xc: case 0xd: case 0xe: case 0xf: + printf("Key pressed: %X\n", l); + break; + case 0x10: + printf("Key pressed: AD\n"); + break; + case 0x11: + printf("Key pressed: DA\n"); + break; + case 0x12: + printf("Key pressed: +\n"); + break; + case 0x13: + printf("Key pressed: GO\n"); + break; + case 0x14: + printf("Key pressed: PC\n"); + break; + } + + last = l; + } + } + } + } + + return 0; +} diff --git a/src/Makefile b/src/Makefile index 8356d0001..034a2230f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -115,7 +115,11 @@ install: $(INSTALL) ../bin/* $(DESTDIR)$(bindir) avail: +ifneq ($(patsubst %,../bin/%,$(PROGS)),$(wildcard $(patsubst %,../bin/%,$(PROGS)))) + $(error executables are missing, please run make first) +else $(foreach prog,$(PROGS),$(AVAIL_recipe)) +endif unavail: $(foreach prog,$(PROGS),$(UNAVAIL_recipe)) diff --git a/src/ca65/ea.h b/src/ca65/ea.h index d861e9a6c..487027c02 100644 --- a/src/ca65/ea.h +++ b/src/ca65/ea.h @@ -43,6 +43,10 @@ /*****************************************************************************/ +/* EffAddr Flags */ +#define EFFADDR_OVERRIDE_ZP 0x00000001UL + + /* GetEA result struct */ typedef struct EffAddr EffAddr; @@ -51,6 +55,7 @@ struct EffAddr { unsigned long AddrModeSet; /* Possible addressing modes */ struct ExprNode* Expr; /* Expression if any (NULL otherwise) */ unsigned Reg; /* Register number in sweet16 mode */ + unsigned long Flags; /* Other properties */ /* The following fields are used inside instr.c */ unsigned AddrMode; /* Actual addressing mode used */ diff --git a/src/ca65/ea65.c b/src/ca65/ea65.c index 275d90b56..5bd2ba82b 100644 --- a/src/ca65/ea65.c +++ b/src/ca65/ea65.c @@ -72,11 +72,13 @@ void GetEA (EffAddr* A) /* Clear the output struct */ A->AddrModeSet = 0; A->Expr = 0; + A->Flags = 0; /* Handle an addressing size override */ switch (CurTok.Tok) { case TOK_OVERRIDE_ZP: Restrictions = AM65_DIR | AM65_DIR_X | AM65_DIR_Y; + A->Flags |= EFFADDR_OVERRIDE_ZP; NextTok (); break; diff --git a/src/ca65/feature.c b/src/ca65/feature.c index b11345338..41177d66b 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -66,6 +66,7 @@ static const char* const FeatureKeys[FEAT_COUNT] = { "addrsize", "bracket_as_indirect", "string_escapes", + "long_jsr_jmp_rts", }; @@ -97,37 +98,30 @@ feature_t FindFeature (const StrBuf* Key) -feature_t SetFeature (const StrBuf* Key) -/* Find the feature and set the corresponding flag if the feature is known. -** In any case, return the feature found. An invalid Key will return -** FEAT_UNKNOWN. +void SetFeature (feature_t Feature, unsigned char On) +/* Set the corresponding feature flag if Feature is valid. */ { - /* Map the string to an enum value */ - feature_t Feature = FindFeature (Key); - /* Set the flags */ switch (Feature) { - case FEAT_DOLLAR_IS_PC: DollarIsPC = 1; break; - case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = 1; break; - case FEAT_LOOSE_STRING_TERM: LooseStringTerm = 1; break; - case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = 1; break; - case FEAT_AT_IN_IDENTIFIERS: AtInIdents = 1; break; - case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = 1; break; - case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= 1; break; - case FEAT_ORG_PER_SEG: OrgPerSeg = 1; break; - case FEAT_PC_ASSIGNMENT: PCAssignment = 1; break; - case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break; - case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break; - case FEAT_C_COMMENTS: CComments = 1; break; - 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; - case FEAT_STRING_ESCAPES: StringEscapes = 1; break; - default: /* Keep gcc silent */ break; + case FEAT_DOLLAR_IS_PC: DollarIsPC = On; break; + case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = On; break; + case FEAT_LOOSE_STRING_TERM: LooseStringTerm = On; break; + case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = On; break; + case FEAT_AT_IN_IDENTIFIERS: AtInIdents = On; break; + case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = On; break; + case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= On; break; + case FEAT_ORG_PER_SEG: OrgPerSeg = On; break; + case FEAT_PC_ASSIGNMENT: PCAssignment = On; break; + case FEAT_MISSING_CHAR_TERM: MissingCharTerm = On; break; + case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = On; break; + case FEAT_C_COMMENTS: CComments = On; break; + case FEAT_FORCE_RANGE: ForceRange = On; break; + case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= On; break; + case FEAT_ADDRSIZE: AddrSize = On; break; + case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = On; break; + case FEAT_STRING_ESCAPES: StringEscapes = On; break; + case FEAT_LONG_JSR_JMP_RTS: LongJsrJmpRts = On; break; + default: break; } - - /* Return the value found */ - return Feature; } diff --git a/src/ca65/feature.h b/src/ca65/feature.h index 876f3c4a8..8eeb62e6f 100644 --- a/src/ca65/feature.h +++ b/src/ca65/feature.h @@ -68,6 +68,7 @@ typedef enum { FEAT_ADDRSIZE, FEAT_BRACKET_AS_INDIRECT, FEAT_STRING_ESCAPES, + FEAT_LONG_JSR_JMP_RTS, /* Special value: Number of features available */ FEAT_COUNT @@ -86,10 +87,8 @@ feature_t FindFeature (const StrBuf* Key); ** feature is invalid, return FEAT_UNKNOWN. */ -feature_t SetFeature (const StrBuf* Key); -/* Find the feature and set the corresponding flag if the feature is known. -** In any case, return the feature found. An invalid Key will return -** FEAT_UNKNOWN. +void SetFeature (feature_t Feature, unsigned char On); +/* Set the corresponding feature flag if Feature is valid. */ diff --git a/src/ca65/global.c b/src/ca65/global.c index 81ff68a79..337677e31 100644 --- a/src/ca65/global.c +++ b/src/ca65/global.c @@ -67,6 +67,7 @@ unsigned char LineCont = 0; /* Allow line continuation */ unsigned char LargeAlignment = 0; /* Don't warn about large alignments */ unsigned char RelaxChecks = 0; /* Relax a few assembler checks */ unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */ +unsigned char LongJsrJmpRts = 0; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */ unsigned char WarningsAsErrors = 0; /* Error if any warnings */ /* Emulation features */ diff --git a/src/ca65/global.h b/src/ca65/global.h index 26877032e..46fb6c763 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -69,6 +69,7 @@ extern unsigned char LineCont; /* Allow line continuation */ extern unsigned char LargeAlignment; /* Don't warn about large alignments */ extern unsigned char RelaxChecks; /* Relax a few assembler checks */ extern unsigned char StringEscapes; /* Allow C-style escapes in strings */ +extern unsigned char LongJsrJmpRts; /* Allow JSR/JMP/RTS as alias for JSL/JML/RTL */ extern unsigned char WarningsAsErrors; /* Error if any warnings */ /* Emulation features */ diff --git a/src/ca65/incpath.c b/src/ca65/incpath.c index 8ea67df6f..461f1ad79 100644 --- a/src/ca65/incpath.c +++ b/src/ca65/incpath.c @@ -75,7 +75,7 @@ void FinishIncludePaths (void) AddSubSearchPathFromEnv (IncSearchPath, "CC65_HOME", "asminc"); /* Add some compiled-in search paths if defined at compile time. */ -#if defined(CA65_INC) && !defined(_WIN32) +#if defined(CA65_INC) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (IncSearchPath, CA65_INC); #endif diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 503304b5b..0afa281b4 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -120,9 +120,21 @@ static void PutJMP (const InsDesc* Ins); ** to check for this case and is otherwise identical to PutAll. */ +static void PutJMP816 (const InsDesc* Ins); +/* Handle the JMP instruction for the 816. +** Allowing the long_jsr_jmp_rts feature to permit a long JMP. +** Note that JMP [abs] and JML [abs] are always both permitted for instruction $DC, +** because the [] notation for long indirection makes the generated instruction unambiguous. +*/ + +static void PutJSR816 (const InsDesc* Ins); +/* Handle the JSR instruction for the 816. +** Allowing the long_jsr_jmp_rts feature to permit a long JSR. +*/ + static void PutRTS (const InsDesc* Ins attribute ((unused))); /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if -** the enclosing scope is FAR. +** the enclosing scope is FAR, but only if the long_jsr_jmp_rts feature applies. */ static void PutAll (const InsDesc* Ins); @@ -169,7 +181,7 @@ static const struct { { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -240,7 +252,7 @@ static const struct { { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -330,7 +342,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x12, 0, PutPCRel8 }, /* DTV */ - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -406,7 +418,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -498,7 +510,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, @@ -610,7 +622,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BSR", 0x0040000, 0x63, 0, PutPCRel4510 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, @@ -735,7 +747,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000005, 0x00, 6, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BRL", 0x0040000, 0x82, 0, PutPCRel16 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, @@ -744,7 +756,7 @@ static const struct { { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll }, - { "COP", 0x0000004, 0x02, 6, PutAll }, + { "COP", 0x0800005, 0x02, 6, PutAll }, { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */ { "CPX", 0x0c0000c, 0xe0, 1, PutAll }, { "CPY", 0x0c0000c, 0xc0, 1, PutAll }, @@ -758,9 +770,9 @@ static const struct { { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "JML", 0x4000010, 0x5c, 1, PutAll }, - { "JMP", 0x4010818, 0x4c, 6, PutAll }, + { "JMP", 0x4010818, 0x4c, 6, PutJMP816 }, { "JSL", 0x0000010, 0x20, 7, PutAll }, - { "JSR", 0x0010018, 0x20, 7, PutAll }, + { "JSR", 0x0010018, 0x20, 7, PutJSR816 }, { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll }, { "LDX", 0x0c0030c, 0xa2, 1, PutAll }, { "LDY", 0x0c0006c, 0xa0, 1, PutAll }, @@ -821,7 +833,7 @@ static const struct { { "TYA", 0x0000001, 0x98, 0, PutAll }, { "TYX", 0x0000001, 0xbb, 0, PutAll }, { "WAI", 0x0000001, 0xcb, 0, PutAll }, - { "WDM", 0x0000004, 0x42, 6, PutAll }, + { "WDM", 0x0800004, 0x42, 6, PutAll }, { "XBA", 0x0000001, 0xeb, 0, PutAll }, { "XCE", 0x0000001, 0xfb, 0, PutAll } } @@ -897,7 +909,7 @@ static const struct { { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, - { "BRK", 0x0000001, 0x00, 0, PutAll }, + { "BRK", 0x0800005, 0x00, 6, PutAll }, { "BSR", 0x0020000, 0x44, 0, PutPCRel8 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, @@ -1257,7 +1269,8 @@ static int EvalEA (const InsDesc* Ins, EffAddr* A) ExprNode* Left = A->Expr->Left; if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) && Left->Op == EXPR_SYMBOL && - GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) { + GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP && + !(A->Flags & EFFADDR_OVERRIDE_ZP)) { /* Output a warning */ Warning (1, "Suspicious address expression"); @@ -1605,7 +1618,7 @@ static void PutJMP (const InsDesc* Ins) if (EvalEA (Ins, &A)) { /* Check for indirect addressing */ - if (A.AddrModeBit & AM65_ABS_IND && CPU < CPU_65SC02) { + if ((A.AddrModeBit & AM65_ABS_IND) && (CPU < CPU_65SC02)) { /* Compare the low byte of the expression to 0xFF to check for ** a page cross. Be sure to use a copy of the expression otherwise @@ -1628,12 +1641,46 @@ static void PutJMP (const InsDesc* Ins) -static void PutRTS (const InsDesc* Ins attribute ((unused))) -/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if -** the enclosing scope is FAR. +static void PutJMP816 (const InsDesc* Ins) +/* Handle the JMP instruction for the 816. +** Allowing the long_jsr_jmp_rts feature to permit a long JMP. +** Note that JMP [abs] and JML [abs] are always both permitted for instruction $DC, +** because the [] notation for long indirection makes the generated instruction unambiguous. */ { - if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) { + if (LongJsrJmpRts) { + PutJMP (Ins); + } else { + InsDesc InsAbs = *Ins; + InsAbs.AddrMode &= ~(AM65_ABS_LONG); + PutJMP (&InsAbs); + } +} + + + +static void PutJSR816 (const InsDesc* Ins) +/* Handle the JSR instruction for the 816. +** Allowing the long_jsr_jmp_rts feature to permit a long JSR. +*/ +{ + if (LongJsrJmpRts) { + PutAll (Ins); + } else { + InsDesc InsAbs = *Ins; + InsAbs.AddrMode &= ~(AM65_ABS_LONG); + PutJMP (&InsAbs); + } +} + + + +static void PutRTS (const InsDesc* Ins attribute ((unused))) +/* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if +** the enclosing scope is FAR, but only if the long_jsr_jmp_rts feature applies. +*/ +{ + if (LongJsrJmpRts && SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) { Emit0 (0x6B); /* RTL */ } else { Emit0 (0x60); /* RTS */ diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 4812b12c4..904c80756 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -390,7 +390,20 @@ void MacDef (unsigned Style) { Macro* M; TokNode* N; + FilePos Pos; int HaveParams; + int LastTokWasSep; + + /* For classic macros, remember if we are at the beginning of the line. + ** If the macro name and parameters pass our checks then we will be on a + ** new line, so set it now + */ + LastTokWasSep = 1; + + /* Save the position of the start of the macro definition to allow + ** using Perror to display the error if .endmacro isn't found + */ + Pos = CurTok.Pos; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { @@ -491,14 +504,16 @@ void MacDef (unsigned Style) while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { - /* In classic macros, only .endmacro is allowed */ - if (CurTok.Tok == TOK_ENDMACRO) { + /* In classic macros, if .endmacro is not at the start of the line + ** it will be added to the macro definition instead of closing it. + */ + if (CurTok.Tok == TOK_ENDMACRO && LastTokWasSep) { /* Done */ break; } /* May not have end of file in a macro definition */ if (CurTok.Tok == TOK_EOF) { - Error ("'.ENDMACRO' expected"); + PError (&Pos, "'.ENDMACRO' expected for macro '%m%p'", &M->Name); goto Done; } } else { @@ -573,6 +588,11 @@ void MacDef (unsigned Style) } ++M->TokCount; + /* Save if last token was a separator to know if .endmacro is at + ** the start of a line + */ + LastTokWasSep = TokIsSep(CurTok.Tok); + /* Read the next token */ NextTok (); } diff --git a/src/ca65/main.c b/src/ca65/main.c index 9710924bf..fedbb0d4b 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -489,12 +489,15 @@ static void OptDebugInfo (const char* Opt attribute ((unused)), static void OptFeature (const char* Opt attribute ((unused)), const char* Arg) /* Set an emulation feature */ { - /* Make a string buffer from Arg */ - StrBuf Feature; + /* Make a string buffer from Arg and use it to find the feature. */ + StrBuf StrFeature; + feature_t Feature = FindFeature (SB_InitFromString (&StrFeature, Arg)); - /* Set the feature, check for errors */ - if (SetFeature (SB_InitFromString (&Feature, Arg)) == FEAT_UNKNOWN) { + /* Enable the feature, check for errors */ + if (Feature == FEAT_UNKNOWN) { AbEnd ("Illegal emulation feature: '%s'", Arg); + } else { + SetFeature (Feature, 1); } } @@ -855,7 +858,12 @@ static void OneLine (void) /* The line has switched the segment */ Size = 0; } - DefSizeOfSymbol (Sym, Size); + /* Suppress .size Symbol if this Symbol already has a multiply-defined error, + ** as it will only create its own additional unnecessary error. + */ + if ((Sym->Flags & SF_MULTDEF) == 0) { + DefSizeOfSymbol (Sym, Size); + } } /* Line separator must come here */ diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 843f5b9d2..1877512d5 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1023,7 +1023,10 @@ static void DoFatal (void) static void DoFeature (void) /* Switch the Feature option */ { - /* Allow a list of comma separated keywords */ + feature_t Feature; + unsigned char On; + + /* Allow a list of comma separated feature keywords with optional +/- or ON/OFF */ while (1) { /* We expect an identifier */ @@ -1034,18 +1037,24 @@ static void DoFeature (void) /* Make the string attribute lower case */ LocaseSVal (); - - /* Set the feature and check for errors */ - if (SetFeature (&CurTok.SVal) == FEAT_UNKNOWN) { + Feature = FindFeature(&CurTok.SVal); + if (Feature == FEAT_UNKNOWN) { /* Not found */ ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal); return; - } else { - /* Skip the keyword */ - NextTok (); + } + NextTok (); + + /* Optional +/- or ON/OFF */ + On = 1; + if (CurTok.Tok != TOK_COMMA && !TokIsSep (CurTok.Tok)) { + SetBoolOption(&On); } - /* Allow more than one keyword */ + /* Apply feature setting. */ + SetFeature (Feature, On); + + /* Allow more than one feature separated by commas. */ if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index bf0a85183..add365e84 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -112,6 +112,7 @@ struct CharSource { CharSource* Next; /* Linked list of char sources */ token_t Tok; /* Last token */ int C; /* Last character */ + int SkipN; /* For '\r\n' line endings, skip '\n\ if next */ const CharSourceFunctions* Func; /* Pointer to function table */ union { InputFile File; /* File data */ @@ -325,6 +326,7 @@ static void UseCharSource (CharSource* S) Source = S; /* Read the first character from the new file */ + S->SkipN = 0; S->Func->NextChar (S); /* Setup the next token so it will be skipped on the next call to @@ -386,6 +388,11 @@ static void IFNextChar (CharSource* S) while (1) { int N = fgetc (S->V.File.F); + if (N == '\n' && S->SkipN) { + N = fgetc (S->V.File.F); + } + S->SkipN = 0; + if (N == EOF) { /* End of file. Accept files without a newline at the end */ if (SB_NotEmpty (&S->V.File.Line)) { @@ -401,9 +408,12 @@ static void IFNextChar (CharSource* S) /* Check for end of line */ } else if (N == '\n') { - /* End of line */ break; + } else if (N == '\r') { + /* End of line, skip '\n' if it's the next character */ + S->SkipN = 1; + break; /* Collect other stuff */ } else { diff --git a/src/ca65/segment.c b/src/ca65/segment.c index 26b568711..aadc35009 100644 --- a/src/ca65/segment.c +++ b/src/ca65/segment.c @@ -306,7 +306,7 @@ void SegAlign (unsigned long Alignment, int FillVal) ActiveSeg->Align = CombinedAlignment; /* Output a warning for larger alignments if not suppressed */ - if (CombinedAlignment >= LARGE_ALIGNMENT && !LargeAlignment) { + if (CombinedAlignment >= LARGE_ALIGNMENT && CombinedAlignment > ActiveSeg->Align && CombinedAlignment > Alignment && !LargeAlignment) { Warning (0, "Combined alignment is suspiciously large (%lu)", CombinedAlignment); } diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index afe7b3ad6..a01d14bd8 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -570,7 +570,18 @@ void SymCheck (void) /* Check for open scopes */ if (CurrentScope->Parent != 0) { - Error ("Local scope was not closed"); + if (CurrentScope->Label) { + /* proc has a label indicating the line it was opened. */ + LIError (&CurrentScope->Label->DefLines, + "Local proc '%s' was not closed", + GetString (CurrentScope->Name)); + } else { + /* scope has no label to track a line number, uses end-of-document line instead. + ** Anonymous scopes will reveal their internal automatic name. + */ + Error ("Local scope '%s' was not closed", + GetString (CurrentScope->Name)); + } } /* First pass: Walk through all symbols, checking for undefined's and diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 4d0151c55..ae40a55e9 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1153,6 +1153,8 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer) /* Save lhs into zeropage */ AddStoreLhsA (D); + /* AddStoreLhsA may have moved the OpIndex, recalculate insertion point to prevent label migration. */ + D->IP = D->OpIndex + 1; /* cmp */ X = NewCodeEntry (OP65_CMP, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI); @@ -1206,6 +1208,8 @@ static unsigned Opt_a_tosicmp (StackOpData* D) /* RHS src is not directly comparable */ X = NewCodeEntry (OP65_STA, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); InsertEntry (D, X, D->Rhs.A.ChgIndex + 1); + /* RHS insertion may have moved the OpIndex, recalculate insertion point to prevent label migration. */ + D->IP = D->OpIndex + 1; /* Cmp with stored RHS */ X = NewCodeEntry (OP65_CMP, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 6907ee099..caa41a7a4 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -803,7 +803,6 @@ const Type* GetStructReplacementType (const Type* SType) switch (SizeOf (SType)) { case 1: NewType = type_uchar; break; case 2: NewType = type_uint; break; - case 3: /* FALLTHROUGH */ case 4: NewType = type_ulong; break; default: NewType = SType; break; } diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 691010b0a..9460569ed 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -3090,9 +3090,10 @@ static void parseadd (ExprDesc* Expr, int DoArrayRef) Expr->Type = Expr2.Type; } else if (!DoArrayRef && IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ - flags = typeadjust (Expr, &Expr2, 0); /* Load rhs into the primary */ LoadExpr (CF_NONE, &Expr2); + /* Adjust rhs primary if needed */ + flags = typeadjust (Expr, &Expr2, 0); } else { /* OOPS */ AddDone = -1; diff --git a/src/cc65/function.c b/src/cc65/function.c index 39f04843f..38a8f45aa 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -601,7 +601,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D) ** We don't currently support this case. */ if (RType == Param->Type) { - Error ("Passing '%s' of this size by value is not supported", GetFullTypeName (Param->Type)); + Error ("Passing '%s' of this size (%d) by value is not supported", GetFullTypeName (Param->Type), SizeOf (RType)); } } diff --git a/src/cc65/incpath.c b/src/cc65/incpath.c index 85f6e070b..3069079ac 100644 --- a/src/cc65/incpath.c +++ b/src/cc65/incpath.c @@ -76,7 +76,7 @@ void FinishIncludePaths (void) AddSubSearchPathFromEnv (SysIncSearchPath, "CC65_HOME", "include"); /* Add some compiled-in search paths if defined at compile time. */ -#if defined(CC65_INC) && !defined(_WIN32) +#if defined(CC65_INC) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (SysIncSearchPath, CC65_INC); #endif diff --git a/src/cl65/main.c b/src/cl65/main.c index 67e9444f4..553fb9ca6 100644 --- a/src/cl65/main.c +++ b/src/cl65/main.c @@ -1216,7 +1216,7 @@ static void OptPrintTargetPath (const char* Opt attribute ((unused)), SearchPaths* TargetPaths = NewSearchPath (); AddSubSearchPathFromEnv (TargetPaths, "CC65_HOME", "target"); -#if defined(CL65_TGT) && !defined(_WIN32) +#if defined(CL65_TGT) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (TargetPaths, CL65_TGT); #endif AddSubSearchPathFromBin (TargetPaths, "target"); diff --git a/src/ld65/bin.c b/src/ld65/bin.c index bd822cc23..15b534f66 100644 --- a/src/ld65/bin.c +++ b/src/ld65/bin.c @@ -193,8 +193,16 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M) NewAddr += M->Start; } if (DoWrite || (M->Flags & MF_FILL) != 0) { - /* Seek in "overwrite" segments */ if (S->Flags & SF_OVERWRITE) { + /* Seek in "overwrite" segments. Fill if the seek position has not been reached yet. */ + unsigned long FileLength; + unsigned long SeekTarget = NewAddr - M->Start + M->FileOffs; + fseek (D->F, 0, SEEK_END); + FileLength = ftell (D->F); + if (SeekTarget > FileLength) { + WriteMult (D->F, M->FillVal, SeekTarget - FileLength); + PrintNumVal ("SF_OVERWRITE", SeekTarget - FileLength); + } fseek (D->F, NewAddr - M->Start + M->FileOffs, SEEK_SET); } else { WriteMult (D->F, M->FillVal, NewAddr-Addr); diff --git a/src/ld65/config.c b/src/ld65/config.c index 6606df7e3..6c1f6ad4c 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1950,6 +1950,10 @@ unsigned CfgProcess (void) /* Remember the start address before handling this segment */ unsigned long StartAddr = Addr; + /* For computing FillLevel */ + unsigned long FillLevel; + unsigned long FillAdded = 0; + /* Take note of "overwrite" segments and make sure there are no ** other segment types following them in current memory region. */ @@ -2039,14 +2043,14 @@ unsigned CfgProcess (void) ++Overflows; if (S->Flags & SF_OFFSET) { CfgWarning (GetSourcePos (S->LI), - "Segment '%s' offset is too small in '%s' by %lu byte%c", + "Segment '%s' offset is too small in '%s' by %lu byte%s", GetString (S->Name), GetString (M->Name), - Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's'); + Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s"); } else { CfgWarning (GetSourcePos (S->LI), - "Segment '%s' start address is too low in '%s' by %lu byte%c", + "Segment '%s' start address is too low in '%s' by %lu byte%s", GetString (S->Name), GetString (M->Name), - Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's'); + Addr - NewAddr, (Addr - NewAddr == 1) ? "" : "s"); } } else { Addr = NewAddr; @@ -2086,14 +2090,19 @@ unsigned CfgProcess (void) /* Increment the fill level of the memory area; and, check for an ** overflow. */ - M->FillLevel = Addr + S->Seg->Size - M->Start; - if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { + FillLevel = Addr + S->Seg->Size - M->Start; + if (FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { ++Overflows; M->Flags |= MF_OVERFLOW; CfgWarning (GetSourcePos (M->LI), - "Segment '%s' overflows memory area '%s' by %lu byte%c", + "Segment '%s' overflows memory area '%s' by %lu byte%s", GetString (S->Name), GetString (M->Name), - M->FillLevel - M->Size, (M->FillLevel - M->Size == 1) ? ' ' : 's'); + FillLevel - M->Size, (FillLevel - M->Size == 1) ? "" : "s"); + } + if (FillLevel > M->FillLevel) { + /* Regular segments increase FillLevel. Overwrite segments may increase but not decrease FillLevel. */ + FillAdded = FillLevel - M->FillLevel; + M->FillLevel = FillLevel; } /* If requested, define symbols for the start and size of the @@ -2112,13 +2121,14 @@ unsigned CfgProcess (void) Addr += S->Seg->Size; /* If this segment will go out to the file, or its place - ** in the file will be filled, then increase the file size, - ** unless it's an OVERWRITE segment. + ** in the file will be filled, then increase the file size. + ** An OVERWRITE segment will only increase the size if it overlapped some of the fill area. */ if (S->Load == M && - ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0) && - (S->Flags & SF_OVERWRITE) == 0) { - M->F->Size += Addr - StartAddr; + ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) { + M->F->Size += (!(S->Flags & SF_OVERWRITE)) ? + (Addr - StartAddr) : + FillAdded; } } diff --git a/src/ld65/filepath.c b/src/ld65/filepath.c index 1ceb2333e..c84fe6f46 100644 --- a/src/ld65/filepath.c +++ b/src/ld65/filepath.c @@ -88,13 +88,13 @@ void InitSearchPaths (void) AddSubSearchPathFromEnv (CfgDefaultPath, "CC65_HOME", "cfg"); /* Add some compiled-in search paths if defined at compile time. */ -#if defined(LD65_LIB) && !defined(_WIN32) +#if defined(LD65_LIB) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (LibDefaultPath, LD65_LIB); #endif -#if defined(LD65_OBJ) && !defined(_WIN32) +#if defined(LD65_OBJ) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (ObjDefaultPath, LD65_OBJ); #endif -#if defined(LD65_CFG) && !defined(_WIN32) +#if defined(LD65_CFG) && !defined(_WIN32) && !defined(_AMIGA) AddSearchPath (CfgDefaultPath, LD65_CFG); #endif diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 10d2cda2c..255b8ccd1 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -230,7 +230,7 @@ Section* ReadSection (FILE* F, ObjData* O) "%lu. Last module requiring alignment was '%s'.", GetString (Name), Alignment, MAX_ALIGNMENT, GetObjFileName (O)); - } else if (Alignment >= LARGE_ALIGNMENT && !LargeAlignment) { + } else if (Alignment >= LARGE_ALIGNMENT && Alignment > S->Alignment && Alignment > Sec->Alignment && !LargeAlignment) { Warning ("Combined alignment for segment '%s' is suspiciously " "large (%lu). Last module requiring alignment was '%s'.", GetString (Name), Alignment, GetObjFileName (O)); diff --git a/src/sp65/lynxsprite.c b/src/sp65/lynxsprite.c index 566edacbe..6bd9b03de 100644 --- a/src/sp65/lynxsprite.c +++ b/src/sp65/lynxsprite.c @@ -312,7 +312,7 @@ static void AssembleByte(unsigned bits, char val) static unsigned char AnalyseNextChunks(signed *newlen, signed len, char data[32], char ColorBits) { char longest = 1; - char prev = 255; + unsigned char prev = 255; char count = 0; char index = 0; char lindex = 0; diff --git a/test/asm/err/endmacro.s b/test/asm/err/endmacro.s new file mode 100644 index 000000000..8907675fb --- /dev/null +++ b/test/asm/err/endmacro.s @@ -0,0 +1,6 @@ +; for PR #2013 +; should produce error output: +; ... Error: '.ENDMACRO' expected for macro 'test' + +.macro test + nop .endmacro diff --git a/test/asm/listing/108-long-rts.s b/test/asm/listing/108-long-rts.s new file mode 100644 index 000000000..a8bf860cd --- /dev/null +++ b/test/asm/listing/108-long-rts.s @@ -0,0 +1,8 @@ +; test of long-rts promotion + +.p816 +.feature long_jsr_jmp_rts +.smart + +.proc farproc : far + rts ; should be $6B (RTL) and not $60 (RTS) +.endproc diff --git a/test/asm/listing/109-brk-signature.s b/test/asm/listing/109-brk-signature.s new file mode 100644 index 000000000..e9c23dd63 --- /dev/null +++ b/test/asm/listing/109-brk-signature.s @@ -0,0 +1,45 @@ +; test of optional signature byte for BRK on all 6502-derived CPUs +; and also COP on 65C816 + +.setcpu "6502" +brk ; 1 byte +brk 0 ; 2 bytes +brk $60 ; 2 bytes +brk #$60 ; 2 bytes + +.setcpu "6502X" +brk +brk $60 +brk #$60 + +.setcpu "6502DTV" +brk +brk $60 +brk #$60 + +.setcpu "65SC02" +brk +brk $60 +brk #$60 + +.setcpu "65816" +brk +brk $60 +brk #$60 +cop +cop $60 +cop #$60 +; WDM is a NOP that gives +2 PC, probably not useful to make its signature byte optional +;wdm +wdm $60 +wdm #$60 + +.setcpu "4510" +brk +brk $60 +brk #$60 + +.setcpu "HuC6280" +brk +brk $60 +brk #$60 diff --git a/test/asm/listing/200-overwrite.cfg b/test/asm/listing/200-overwrite.cfg new file mode 100644 index 000000000..b7b2fee49 --- /dev/null +++ b/test/asm/listing/200-overwrite.cfg @@ -0,0 +1,20 @@ +MEMORY +{ + A: start = 0, size = 8, file = %O, fill = yes, fillval = $33; + B: start = 8, size = 8, file = %O, fill = yes, fillval = $44; + C: start = 0, size = 8, file = %O, fill = yes, fillval = $55; + D: start = 8, size = 8, file = %O, fill = no, fillval = $66; +} +SEGMENTS +{ + A: load = A, type = ro; + B: load = B, type = ro; + C0: load = C, type = ro; + C1: load = C, type = ro, start = 5; + D: load = D, type = ro; + + AO: load = A, type = overwrite, start = 4; + BO: load = B, type = overwrite, start = 8+5; + CO: load = C, type = overwrite, start = 2; + DO: load = D, type = overwrite, start = 8+4; +} diff --git a/test/asm/listing/200-overwrite.s b/test/asm/listing/200-overwrite.s new file mode 100644 index 000000000..cd2349c6a --- /dev/null +++ b/test/asm/listing/200-overwrite.s @@ -0,0 +1,29 @@ +; verification of overwrite segment feature +; See: https://github.com/cc65/cc65/issues/1366 + +; A: full memory area which is overwritten to the end +.segment "A" +.byte 0,1,2,3,4,5,6,7 +.segment "AO" +.byte $24,$25,$26,$27 + +; B: incomplete memory area overwritten in the fill area +.segment "B" +.byte 0,1,2 +.segment "BO" +.byte $25,$26 + +; C: memory area with gap overwritten across the gap +.segment "C0" +.byte 0,1,2 +.segment "C1" +.byte 5,6,7 +.segment "CO" +.byte $22,$23,$24,$25 + +; D: incomplete memory area without fill, +; but overwrite extends past existing segments +.segment "D" +.byte 0,1,2 +.segment "DO" +.byte $24,$25 diff --git a/test/asm/listing/201-overwrite-overflow.cfg b/test/asm/listing/201-overwrite-overflow.cfg new file mode 100644 index 000000000..cada57d5a --- /dev/null +++ b/test/asm/listing/201-overwrite-overflow.cfg @@ -0,0 +1,12 @@ +MEMORY +{ + A: start = 0, size = 8, file = %O, fill = yes, fillval = $33; + B: start = 8, size = 8, file = %O, fill = yes, fillval = $44; +} +SEGMENTS +{ + A: load = A, type = ro; + B: load = B, type = ro; + AO: load = A, type = overwrite, start = 6; + BO: load = B, type = overwrite, start = 8+6; +} diff --git a/test/asm/listing/201-overwrite-overflow.s b/test/asm/listing/201-overwrite-overflow.s new file mode 100644 index 000000000..156388ab5 --- /dev/null +++ b/test/asm/listing/201-overwrite-overflow.s @@ -0,0 +1,13 @@ +; verification of overwrite segment overflow cases + +; error: overflow past end of A memory area +.segment "A" +.byte 0,1,2,3 +.segment "AO" +.byte $26,$27,$28 + +; error: overflow past end of B memory area +.segment "B" +.byte 0,1,2,3 +.segment "BO" +.byte $26,$27,$28 diff --git a/test/asm/listing/Makefile b/test/asm/listing/Makefile index 3c4c404af..23aa3969c 100644 --- a/test/asm/listing/Makefile +++ b/test/asm/listing/Makefile @@ -58,12 +58,20 @@ $(WORKDIR)/$1.bin: $1.s $(ISEQUAL) ifeq ($(wildcard control/$1.err),) $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2> $$(@:.bin=.err2) ifeq ($(wildcard control/$1.no-ld65),) +ifeq ($(wildcard $1.cfg),) $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) +else + $(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) +endif endif else $(CA65) -t none -o $$(@:.bin=.o) $$< > $$(@:.bin=.err) 2> $$(@:.bin=.err2) || $(TRUE) ifeq ($(wildcard control/$1.no-ld65),) +ifeq ($(wildcard $1.cfg),) $(LD65) -t none -o $$@ $$(@:.bin=.o) none.lib > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE) +else + $(LD65) -C $$(<:.s=.cfg) -o $$@ $$(@:.bin=.o) > $$(@:.bin=.ld65-err) 2> $$(@:.bin=.ld65-err2) || $(TRUE) +endif endif endif @@ -117,12 +125,20 @@ endif ifeq ($(wildcard control/$1.err),) $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2> $$(@:.bin=.list-err2) ifeq ($(wildcard control/$1.no-ld65),) +ifeq ($(wildcard $1.cfg),) $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) +else + $(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) +endif endif else $(CA65) -t none -l $$(@:.bin=.list-lst) -o $$(@:.bin=.list-o) $$< > $$(@:.bin=.list-err) 2> $$(@:.bin=.list-err2) || $(TRUE) ifeq ($(wildcard control/$1.no-ld65),) +ifeq ($(wildcard $1.cfg),) $(LD65) -t none -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) none.lib > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE) +else + $(LD65) -C $$(<:.s=.cfg) -o $$(@:.bin=.list-bin) $$(@:.bin=.list-o) > $$(@:.bin=.list-ld65-err) 2> $$(@:.bin=.list-ld65-err2) || $(TRUE) +endif endif endif diff --git a/test/asm/listing/control/201-overwrite-overflow.err b/test/asm/listing/control/201-overwrite-overflow.err new file mode 100644 index 000000000..e69de29bb diff --git a/test/asm/listing/readme.txt b/test/asm/listing/readme.txt index e43f2008a..5436b234a 100644 --- a/test/asm/listing/readme.txt +++ b/test/asm/listing/readme.txt @@ -4,24 +4,42 @@ Overall test: These testcases can be used to test different aspects of the assembler. The name of a test is everything in the form .s. +If a custom linker configuration is needed, also include .cfg. + The following reference files can be added: -- .bin-ref: +- ref/.bin-ref: This is a reference for the resulting binary. The binary as binary tested against this file. If they are not equal, the test fails. -- .list-ref +- ref/.list-ref This is a reference for the resulting listing output This file *must* have the first line of the listing removed, as that contains a ca65 version string, and almost always this will be changed! +- ref/.err-ref + This is a reference for the resulting ca65 stdout (>) output. + +- ref/.err2-ref + This is a reference for the resulting ca65 stderr (2>) output. + +- ref/.ld65err-ref + This is a reference for the resutling ld65 stdout (>) output. + +- ref/.ld65err2-ref + This is a reference for the resulting ld65 stderr (2>) output. + +The following control files can be added to control the tests. +These files are empty (contents ignored), and only the filename is used: + +- control/.err + Test is expected to produce an error. + +- control/.no-ld65 + Skip the ld65 step. + Note that the resulting .bin file is generated twice: Once with no listing file, and once with listing file. This way, one can find out if the listing file generation changes anything with the resulting binary output. - - -TODO: -- add the possibility to test for specific error output that are to be - expected diff --git a/test/asm/listing/ref/108-long-rts.bin-ref b/test/asm/listing/ref/108-long-rts.bin-ref new file mode 100644 index 000000000..23fa7d31a --- /dev/null +++ b/test/asm/listing/ref/108-long-rts.bin-ref @@ -0,0 +1 @@ +k \ No newline at end of file diff --git a/test/asm/listing/ref/109-brk-signature.bin-ref b/test/asm/listing/ref/109-brk-signature.bin-ref new file mode 100644 index 000000000..0eaa09faa Binary files /dev/null and b/test/asm/listing/ref/109-brk-signature.bin-ref differ diff --git a/test/asm/listing/ref/200-overwrite.bin-ref b/test/asm/listing/ref/200-overwrite.bin-ref new file mode 100644 index 000000000..b3a6f4f63 Binary files /dev/null and b/test/asm/listing/ref/200-overwrite.bin-ref differ diff --git a/test/asm/listing/ref/201-overwrite-overflow.ld65err2-ref b/test/asm/listing/ref/201-overwrite-overflow.ld65err2-ref new file mode 100644 index 000000000..e372938ef --- /dev/null +++ b/test/asm/listing/ref/201-overwrite-overflow.ld65err2-ref @@ -0,0 +1,3 @@ +ld65: Warning: 201-overwrite-overflow.cfg:3: Segment 'AO' overflows memory area 'A' by 1 byte +ld65: Warning: 201-overwrite-overflow.cfg:4: Segment 'BO' overflows memory area 'B' by 1 byte +ld65: Error: Cannot generate most of the files due to memory area overflows diff --git a/test/asm/readme.txt b/test/asm/readme.txt index c3198c12a..49b530d1c 100644 --- a/test/asm/readme.txt +++ b/test/asm/readme.txt @@ -1,32 +1,38 @@ Assembler Testcases =================== -Opcode Tests: -------------- +cpudetect +--------- -these go into opcodes/. Refer to opcodes/readme.txt +Tests the --cpu command line option of ca65/ld65. +Refer to cpudetect/readme.txt -CPU Detect Tests ----------------- +opcodes +------- -these go into cpudetect/. Refer to cpudetect/readme.txt +Test of assembler opcodes for each CPU. +Refer to opcodes/readme.txt -Overall tests: --------------- - -These go into listing/. Refer to listing/readme.txt - -val: ----- - -Works very much like the /val directory used to test the compiler - individual -tests are run in the simulator and should exit with an exit code of 0 when they -pass, or either -1 or a number indicating what part of the test failed on error. - err: ---- -Works very much like the /err directory used to test the compiler - individual -tests are assembled and MUST NOT assemble without error. +Used to test assembler errors. These tests MUST NOT assemble without error. + + +listing: +-------- + +This is the most versatile assembler test form, allowing control customizations, +reference tests for binary output, stdout and error text ouput, error tests, +listings, custom linker configuration, etc. as needed. +Refer to listing/readme.txt + + +val: +---- + +Runtime assembly tests using sim65 that should end with an exit code of 0 if +they pass. If they fail the exit code should be either -1, or a number +indicating what part of the test failed. diff --git a/test/asm/val/endmacro.s b/test/asm/val/endmacro.s new file mode 100644 index 000000000..cfb8efefb --- /dev/null +++ b/test/asm/val/endmacro.s @@ -0,0 +1,30 @@ +; for PR #2013 + .import _exit + .export _main + + ; this macro is invalid, but should not cause an error (if it is never expanded) + .macro invalid + nop .endmacro + .endmacro + + .define temp_endmac .endmacro + .macro new_mac + .define startmac .macro + .define endmac .endmacro + temp_endmac + + .undefine temp_endmac + + new_mac + + startmac dex2 + dex + dex + endmac + +_main: + ldx #$02 + dex2 + ; x should be zero + txa + jmp _exit diff --git a/test/asm/val/feature.s b/test/asm/val/feature.s new file mode 100644 index 000000000..4428cf4c2 --- /dev/null +++ b/test/asm/val/feature.s @@ -0,0 +1,147 @@ +; a simple test of every .feature + +.export _main + +.segment "ZEROPAGE" +zplabel: + +.segment "CODE" +abslabel: + +; exit with 0 + +_main: + ; if any feature needs a runtime test, + ; it can be added here. + lda #0 + tax + rts + + +.feature addrsize + +.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE" +.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute" +.feature addrsize - + + +.feature at_in_identifiers on +ident@with@at: + rts +.feature at_in_identifiers off + + +.feature bracket_as_indirect + lda [$82],y +.feature bracket_as_indirect- + + +.feature c_comments + lda zplabel /* comment */ + /* comment */ +/* multiline +** comment +*/ +.feature c_comments - + + +.feature dollar_in_identifiers +ident$with$dollar: + rts +.feature dollar_in_identifiers - + + +.feature dollar_is_pc +.assert $ = *, error, "dollar_is_pc failure" +.feature dollar_is_pc - + + +.feature force_range + lda #-1 +.feature force_range - + + +.feature labels_without_colons +labelwithoutcolon + jmp labelwithoutcolon +.feature labels_without_colons - + + +.feature leading_dot_in_identifiers +.identifierwithdot: + rts +.feature leading_dot_in_identifiers - + + +.feature long_jsr_jmp_rts +.p816 + ; long addresses require alternate instruction names JSL, JML without this feature + jsr $123456 + jmp $123456 +; smart + far + long_jsr_jmp_rts will promote rts to rtl +.smart + +.proc long_rts : far + rts ; should become RTL ($6B) instead of RTS ($60) + ; the emitted opcode is not verified by this test, + ; see test/asm/listing/108-long-rts +.endproc +.smart - +.p02 +.feature long_jsr_jmp_rts - + + +.feature loose_char_term +.byte 'a' +.byte "a" +.feature loose_char_term - + + +.feature loose_string_term +.asciiz "string" +.asciiz 'string' +.feature loose_string_term - + + +.feature missing_char_term + lda #'a +.feature missing_char_term - + + +.feature org_per_seg +.segment "RODATA" +.org $5678 +.assert * = $5678, error, "org_per_seg failed" +.segment "CODE" +.org $9ABC +.assert * = $9ABC, error, "org_per_seg failed" +.segment "RODATA" +.assert * = $5678, error, "org_per_seg failed" +.reloc +.segment "CODE" +.assert * = $9ABC, error, "org_per_seg failed" +.reloc +.feature org_per_seg - + + +.feature pc_assignment +* = $1234 +.assert * = $1234, error, "pc_assignment failed" +.reloc +.feature pc_assignment - + + +.feature string_escapes +.asciiz "quote:\"" +.feature string_escapes - + + +.feature ubiquitous_idents +.macro bit + brk +.endmacro + bit +.feature ubiquitous_idents - + + +.feature underline_in_numbers +.byte %10_10_10_10 +.feature underline_in_numbers - diff --git a/test/dasm/65816.info b/test/dasm/65816.info index 2a3394680..a6d836688 100644 --- a/test/dasm/65816.info +++ b/test/dasm/65816.info @@ -3,5 +3,5 @@ GLOBAL { }; RANGE { START $8000; END $8229; ADDRMODE "MX"; TYPE Code;}; -RANGE { START $822a; END $824b; ADDRMODE "mx"; TYPE Code;}; +RANGE { START $822a; END $825b; ADDRMODE "mx"; TYPE Code;}; diff --git a/test/dasm/test65816.s b/test/dasm/test65816.s index 3d764fb6e..1b447d0fe 100644 --- a/test/dasm/test65816.s +++ b/test/dasm/test65816.s @@ -151,10 +151,11 @@ BVC LABEL BVS LABEL BRL LABEL JMP $1234 -JMP $FEDCBA +JML $FEDCBA JMP ($1234) JMP ($1234,X) JMP [$1234] +JML [$1234] ; alternative to JMP [] JSL $123456 JSR $1234 JSR ($1234,X) @@ -271,3 +272,15 @@ BIT #$5432 LDA #$5432 LDX #$5432 LDY #$5432 + +; test of smart and long_jsr_jmp_rts +.smart +.proc short_rts : far +RTS ; not promoted to RTL +.endproc +.feature long_jsr_jmp_rts +JSR $FEDCBA ; promoted to JSL +JMP $FEDCBA ; promoted to JML +.proc long_rts : far +RTS ; promoted to RTL +.endproc diff --git a/test/val/bug1989.c b/test/val/bug1989.c new file mode 100644 index 000000000..b3e3d4c8d --- /dev/null +++ b/test/val/bug1989.c @@ -0,0 +1,40 @@ + +/* bug #1989 - OptStackOps Opt_a_toscmpbool bypassed a comparison, discovered in 544a49c */ + +#include + +unsigned char i,r,j; + +void fail() // for the r=0 case, the == comparison was getting jumped over by OptStackOps +{ + if ((i & 0x1f) == (r ? 0 : 16)) j -=8; +} + +void pass() +{ + if ((i & 0x1f) == (unsigned char)(r ? 0 : 16)) j -= 8; +} + +void test(unsigned char ti, unsigned char tr, unsigned char tj) +{ + unsigned char rj; + i = ti; + r = tr; + j = tj; + pass(); + rj = j; + i = ti; + r = tr; + j = tj; + fail(); + if (j != rj) exit(1); +} + +int main(void) +{ + test( 1,0,33); + test( 0,0,33); + test( 1,1,33); + test(16,1,33); + return 0; +} diff --git a/test/val/bug2060.c b/test/val/bug2060.c new file mode 100644 index 000000000..59b4774a4 --- /dev/null +++ b/test/val/bug2060.c @@ -0,0 +1,56 @@ +/* Test of bug: https://github.com/cc65/cc65/issues/2060 */ + +#include + +#define W 320 + +unsigned long test1(unsigned char* p, unsigned long n) +{ + (void)p; + return n; +} + +unsigned long test0(unsigned char* p, int x, int y, unsigned char b) +{ + (void)b; + return test1(p, (long)y * W + x); +} + +#define TEST(ta,tb) \ + expect = (long)tb * W + ta; \ + result = test0(p,ta,tb,0x56); \ + printf("%4d * %3d + %4d = %08lx",tb,W,ta,result); \ + if (expect != result) { printf(" expected: %08lx\n",expect); ++fail; } \ + else printf("\n"); + +int main(void) +{ + unsigned char* p = (unsigned char*)0x1234; + unsigned long expect, result; + int fail = 0; + + TEST(1,3); + TEST(50,60); + TEST(99,88); + TEST(128,102); + TEST(129,102); + TEST(320,102); + /* Bug 2060 indicated failure when y > 102. + Because: (y * 320) > 32767 + The promotion of x from int to long had an incorrect high word, + because it was done before loading x into AX, rather than after. + */ + TEST(0,103); + TEST(150,170); + TEST(300,180); + /* x < 0 also fails because its high word sign extend is incorrect. */ + TEST(-100,50); + TEST(-49,99); + TEST(-300,-180); + /* This passed despite the bug, because y * 320 coincidentally had the + same high word. + */ + TEST(-1,-1); + + return fail; +} diff --git a/test/val/bug895.c b/test/val/bug895.c index c4892d7b1..3c0331a6d 100644 --- a/test/val/bug895.c +++ b/test/val/bug895.c @@ -21,7 +21,7 @@ unsigned int uia, uib; unsigned long ula, ulb; #define OPTCMP8TEST_SINGLE(num,cmpop,asmprefix,vara,varb,b0,b1,a0,a1,typename,name) \ - typename name ## _ ## num ## (void) { \ + typename name ## _ ## num(void) { \ varb = b0; \ asm( asmprefix ); \ vara = a0; \ @@ -30,7 +30,7 @@ unsigned long ula, ulb; } #define OPTCMP8TEST_VERIFY(num,b,desc,printterm,name) \ - ASSERT_AreEqual(name ## _ ## num ##(),b,printterm,"Incorrect optimization of const comparison (" #name "_" #num ": " desc ")."); + ASSERT_AreEqual(name ## _ ## num(),b,printterm,"Incorrect optimization of const comparison (" #name "_" #num ": " desc ")."); /* Generates a set of comparison tests for one type and set of test values. ** name = a name for this test (no spaces) diff --git a/test/val/struct-by-value.c b/test/val/struct-by-value.c new file mode 100644 index 000000000..0e846c117 --- /dev/null +++ b/test/val/struct-by-value.c @@ -0,0 +1,144 @@ +/* Test of passing and returning structs by value. + Structs of 1, 2 and 4 bytes are supported. + Note that structs of 3 bytes are disabled, see: + https://github.com/cc65/cc65/issues/2022 +*/ + +int fail = 0; + +struct s1 { char a; }; +struct s2 { char a, b; }; +struct s3 { char a, b, c; }; +struct s4 { char a, b, c, d; }; + +const struct s1 c1 = { 1 }; +const struct s2 c2 = { 2, 3 }; +const struct s3 c3 = { 4, 5, 6 }; +const struct s4 c4 = { 7, 8, 9, 10 }; + +struct s1 return1() { return c1; } +struct s2 return2() { return c2; } +/*struct s3 return3() { return c3; }*/ +struct s4 return4() { return c4; } + +int compare1(struct s1 a, struct s1 b) +{ + if (a.a != b.a) return 1; + return 0; +} + +int compare2(struct s2 a, struct s2 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + return 0; +} + +/*int compare3(struct s3 a, struct s3 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + if (a.c != b.c) return 1; + return 0; +}*/ + +int compare4(struct s4 a, struct s4 b) +{ + if (a.a != b.a) return 1; + if (a.b != b.b) return 1; + if (a.c != b.c) return 1; + if (a.d != b.d) return 1; + return 0; +} + +int pass1(struct s1 p1) +{ + struct s1 a1; + a1 = p1; + if (a1.a != c1.a) return 1; + return 0; +} + +int pass2(struct s2 p2) +{ + struct s2 a2; + a2 = p2; + if (a2.a != c2.a) return 1; + if (a2.b != c2.b) return 1; + return 0; +} + +/*int pass3(struct s3 p3) +{ + struct s3 a3; + a3 = p3; + if (a3.a != c3.a) return 1; + if (a3.b != c3.b) return 1; + if (a3.c != c3.c) return 1; + return 0; +}*/ + +int pass4(struct s4 p4) +{ + struct s4 a4; + a4 = p4; + if (a4.a != c4.a) return 1; + if (a4.b != c4.b) return 1; + if (a4.c != c4.c) return 1; + if (a4.d != c4.d) return 1; + return 0; +} + +void reset(char* gg) +{ + char i; + for (i=0;i<5;++i) gg[i] = 128+i; +} + +int test(char* gg, char start) +{ + char i; + for (i=start;i<5;++i) + if (gg[i] != 128+i) return 1; + return 0; +} + +int main() +{ + /* Used to check #2022 bug condition of extra bytes being overwritten. */ + union + { + char gg[5]; + struct s1 g1; + struct s2 g2; + struct s3 g3; + struct s4 g4; + } guard; + + reset(guard.gg); + guard.g1 = return1(); + fail += compare1(guard.g1,c1); + fail += test(guard.gg,1); + + reset(guard.gg); + guard.g2 = return2(); + fail += compare2(guard.g2,c2); + fail += test(guard.gg,2); + + /*reset(guard.gg); + guard.g3 = return3(); + fail += compare3(guard.g3,c3); + fail += test(guard.gg,3);*/ + + reset(guard.gg); + guard.g4 = return4(); + fail += compare4(guard.g4,c4); + fail += test(guard.gg,4); + + fail += pass1(c1); + fail += pass2(c2); + /*fail += pass3(c3);*/ + fail += pass4(c4); + + return fail; +}