]> git.sur5r.net Git - cc65/commitdiff
Merge pull request #405 from IrgendwerA8/65SC02_sim65_support
authorOliver Schmidt <ol.sc@web.de>
Sat, 18 Mar 2017 22:38:05 +0000 (23:38 +0100)
committerGitHub <noreply@github.com>
Sat, 18 Mar 2017 22:38:05 +0000 (23:38 +0100)
Added 65SC02 support for simulator.

48 files changed:
.gitattributes [new file with mode: 0644]
asminc/creativision.inc
asminc/opcodes.inc
asminc/smc.inc
asminc/telestrat.inc
cfg/creativision.cfg
doc/cc65.sgml
doc/telestrat.sgml
include/osic1p.h
include/zlib.h
libsrc/Makefile
libsrc/c64/emd/c64-65816.s
libsrc/creativision/clrscr.s
libsrc/creativision/cputc.s
libsrc/creativision/crt0.s
libsrc/creativision/joy/creativision-stdjoy.s
libsrc/creativision/mainargs.s [deleted file]
libsrc/osic1p/cgetc.s
libsrc/osic1p/osic1p.inc
libsrc/osic1p/osiscreen.inc
libsrc/telestrat/clrscr.s [new file with mode: 0644]
libsrc/telestrat/gotox.s [new file with mode: 0644]
libsrc/telestrat/gotoxy.s [new file with mode: 0644]
libsrc/telestrat/gotoy.s [new file with mode: 0644]
libsrc/telestrat/wherex.s [new file with mode: 0644]
libsrc/telestrat/wherey.s [new file with mode: 0644]
samples/Makefile
src/cc65/compile.c
src/cc65/datatype.c
src/cc65/declare.c
src/cc65/symtab.c
test/err/duplicate-global-static.c [new file with mode: 0644]
test/err/duplicate-global.c [new file with mode: 0644]
test/err/duplicate-static-global.c [new file with mode: 0644]
test/err/duplicate-static.c [new file with mode: 0644]
test/err/void-empty.c [new file with mode: 0644]
test/err/void-size2.c [new file with mode: 0644]
test/ref/Makefile
test/ref/divmod.c
test/ref/init.c
test/ref/pointer2.c
test/ref/switch2.c
test/ref/varargs.c
test/ref/yacc.c
test/val/static-fwd-decl.c [new file with mode: 0644]
test/val/void-size1.c [new file with mode: 0644]
testcode/lib/atari/displaylist.c
testcode/lib/mul-test.c

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..176a458
--- /dev/null
@@ -0,0 +1 @@
+* text=auto
index 59b26101bbfcf9ce89b3aed80ad7a314aa930b00..49d55a3425362572563cda823af5d728bffa9d8c 100644 (file)
@@ -10,10 +10,10 @@ CURSOR_X                = $3C
 CURSOR_Y                = $3D
 
 ;** VDP
-VDP_CONTROL_W           = $3001
-VDP_DATA_W              = $3000
-VDP_STATUS_R            = $2001
 VDP_DATA_R              = $2000
+VDP_STATUS_R            = $2001
+VDP_DATA_W              = $3000
+VDP_CONTROL_W           = $3001
 
 ;** PIA
 PIA0_DATA               = $1000
@@ -36,7 +36,26 @@ ZP_JOY1_DIR             = $13
 ZP_JOY0_BUTTONS         = $16
 ZP_JOY1_BUTTONS         = $17
 
+;** Joystick direction values (ZP_JOY0_DIR/ZP_JOY1_DIR)
+JOY_N                   = $49
+JOY_NNE                 = $48
+JOY_NE                  = $47
+JOY_ENE                 = $46
+JOY_E                   = $45
+JOY_ESE                 = $44
+JOY_SE                  = $43
+JOY_SSE                 = $42
+JOY_S                   = $41
+JOY_SSW                 = $40
+JOY_SW                  = $4F
+JOY_WSW                 = $4E
+JOY_W                   = $4D
+JOY_WNW                 = $4C
+JOY_NW                  = $4B
+JOY_NNW                 = $4A
+
 ;** BIOS
 BIOS_IRQ1_ADDR          = $FF3F
 BIOS_IRQ2_ADDR          = $FF52
 BIOS_NMI_RESET_ADDR     = $F808
+BIOS_WRITE_VDP_REG      = $FE1F
index 7c52871d2afbb01cc06b5910361c22286a0ead26..96cdefb65e2e99f640fa69bf743d27b4a01381aa 100644 (file)
-; opcodes.inc\r
-; ca65 6502 - opcode definitions, mainly for self modifying code\r
-;\r
-; Christian Krüger, latest change: 18-Sep-2010\r
-;\r
-; This software is provided 'as-is', without any expressed or implied      \r
-; warranty.  In no event will the authors be held liable for any damages   \r
-; arising from the use of this software.                                   \r
-;                                                                          \r
-; Permission is granted to anyone to use this software for any purpose,    \r
-; including commercial applications, and to alter it and redistribute it   \r
-; freely, subject to the following restrictions:                           \r
-;                                                                          \r
-; 1. The origin of this software must not be misrepresented; you must not  \r
-;    claim that you wrote the original software. If you use this software  \r
-;    in a product, an acknowledgment in the product documentation would be \r
-;    appreciated but is not required.                                      \r
-; 2. Altered source versions must be plainly marked as such, and must not  \r
-;    be misrepresented as being the original software.                     \r
-; 3. This notice may not be removed or altered from any source             \r
-;    distribution.                                                         \r
-;                                                                          \r
-\r
-; Opcode-Table\r
-; ------------\r
-; Post fix explanation:\r
-; imm = #$00\r
-; zp = $00\r
-; zpx = $00,X\r
-; zpy = $00,Y\r
-; izp = ($00)\r
-; izx = ($00,X)\r
-; izy = ($00),Y\r
-; abs = $0000\r
-; abx = $0000,X\r
-; aby = $0000,Y\r
-; ind = ($0000)\r
-; iax = ($0000,X)\r
-; rel = $0000 (PC-relative) (supressed here)\r
-\r
-.macpack        cpu\r
-\r
-OPC_BRK     = $00\r
-OPC_ORA_izx = $01\r
-OPC_ORA_zp  = $05\r
-OPC_ASL_zp  = $06\r
-OPC_PHP     = $08\r
-OPC_ORA_imm = $09\r
-OPC_ASL     = $0A\r
-OPC_ORA_abs = $0D\r
-OPC_ASL_abs = $0E\r
-\r
-OPC_BPL     = $10\r
-OPC_ORA_izy = $11\r
-OPC_ORA_zpx = $15\r
-OPC_ASL_zpx = $16\r
-OPC_CLC     = $18\r
-OPC_ORA_aby = $19\r
-OPC_ORA_abx = $1D\r
-OPC_ASL_abx = $1E\r
-\r
-OPC_JSR_abs = $20\r
-OPC_AND_izx = $21\r
-OPC_BIT_zp  = $24\r
-OPC_AND_zp  = $25\r
-OPC_ROL_zp  = $26\r
-OPC_PLP     = $28\r
-OPC_AND_imm = $29\r
-OPC_ROL     = $2A\r
-OPC_BIT_abs = $2C\r
-OPC_AND_abs = $2D\r
-OPC_ROL_abs = $2E\r
-\r
-OPC_BMI     = $30\r
-OPC_AND_izy = $31\r
-OPC_AND_zpx = $35\r
-OPC_ROL_zpx = $36\r
-OPC_SEC     = $38\r
-OPC_AND_aby = $39\r
-OPC_AND_abx = $3D\r
-OPC_ROL_abx = $3E\r
-\r
-\r
-OPC_RTI     = $40\r
-OPC_EOR_izx = $41\r
-OPC_EOR_zp  = $45\r
-OPC_LSR_zp  = $46\r
-OPC_PHA     = $48\r
-OPC_EOR_imm = $49\r
-OPC_LSR     = $4A\r
-OPC_JMP_abs = $4C\r
-OPC_EOR_abs = $4D\r
-OPC_LSR_abs = $4E\r
-\r
-OPC_BVC     = $50\r
-OPC_EOR_izy = $51\r
-OPC_EOR_zpx = $55\r
-OPC_LSR_zpx = $56\r
-OPC_CLI     = $58\r
-OPC_EOR_aby = $59\r
-OPC_EOR_abx = $5D\r
-OPC_LSR_abx = $5E\r
-\r
-OPC_RTS     = $60\r
-OPC_ADC_izx = $61\r
-OPC_ADC_zp  = $65\r
-OPC_ROR_zp  = $66\r
-OPC_PLA     = $68\r
-OPC_ADC_imm = $69\r
-OPC_ROR     = $6A\r
-OPC_JMP_ind = $6C\r
-OPC_ADC_abs = $6D\r
-OPC_ROR_abs = $6E\r
-\r
-OPC_BVS     = $70\r
-OPC_ADC_izy = $71\r
-OPC_ADC_zpx = $75\r
-OPC_ROR_zpx = $76\r
-OPC_SEI     = $78\r
-OPC_ADC_aby = $79\r
-OPC_ADC_abx = $7D\r
-OPC_ROR_abx = $7E\r
-\r
-OPC_STA_izx = $81\r
-OPC_STY_zp  = $84\r
-OPC_STA_zp  = $85\r
-OPC_STX_zp  = $86\r
-OPC_DEY     = $88\r
-OPC_TXA     = $8A\r
-OPC_STY_abs = $8C\r
-OPC_STA_abs = $8D\r
-OPC_STX_abs = $8E\r
-\r
-OPC_BCC     = $90\r
-OPC_STA_izy = $91\r
-OPC_STY_zpx = $94\r
-OPC_STA_zpx = $95\r
-OPC_STX_zpy = $96\r
-OPC_TYA     = $98\r
-OPC_STA_aby = $99\r
-OPC_TXS     = $9A\r
-OPC_STA_abx = $9D\r
-\r
-OPC_LDY_imm = $A0\r
-OPC_LDA_izx = $A1\r
-OPC_LDX_imm = $A2\r
-OPC_LDY_zp  = $A4\r
-OPC_LDA_zp  = $A5\r
-OPC_LDX_zp  = $A6\r
-OPC_TAY     = $A8\r
-OPC_LDA_imm = $A9\r
-OPC_TAX     = $AA\r
-OPC_LDY_abs = $AC\r
-OPC_LDA_abs = $AD\r
-OPC_LDX_abs = $AE\r
-\r
-OPC_BCS     = $B0\r
-OPC_LDA_izy = $B1\r
-OPC_LDY_zpx = $B4\r
-OPC_LDA_zpx = $B5\r
-OPC_LDX_zpy = $B6\r
-OPC_CLV     = $B8\r
-OPC_LDA_aby = $B9\r
-OPC_TSX     = $BA\r
-OPC_LDY_abx = $BC\r
-OPC_LDA_abx = $BD\r
-OPC_LDX_aby = $BE\r
-\r
-OPC_CPY_imm = $C0\r
-OPC_CMP_izx = $C1\r
-OPC_CPY_zp  = $C4\r
-OPC_CMP_zp  = $C5\r
-OPC_DEC_zp  = $C6\r
-OPC_INY     = $C8\r
-OPC_CMP_imm = $C9\r
-OPC_DEX     = $CA\r
-OPC_CPY_abs = $CC\r
-OPC_CMP_abs = $CD\r
-OPC_DEC_abs = $CE\r
-\r
-OPC_BNE     = $D0\r
-OPC_CMP_izy = $D1\r
-OPC_CMP_zpx = $D5\r
-OPC_DEC_zpx = $D6\r
-OPC_CLD     = $D8\r
-OPC_CMP_aby = $D9\r
-OPC_CMP_abx = $DD\r
-OPC_DEC_abx = $DE\r
-\r
-OPC_CPX_imm = $E0\r
-OPC_SBC_izx = $E1\r
-OPC_CPX_zp  = $E4\r
-OPC_SBC_zp  = $E5\r
-OPC_INC_zp  = $E6\r
-OPC_INX     = $E8\r
-OPC_SBC_imm = $E9\r
-OPC_NOP     = $EA\r
-OPC_CPX_abs = $EC\r
-OPC_SBC_abs = $ED\r
-OPC_INC_abs = $EE\r
-\r
-\r
-OPC_BEQ     = $F0\r
-OPC_SBC_izy = $F1\r
-OPC_SBC_zpx = $F5\r
-OPC_INC_zpx = $F6\r
-OPC_SED     = $F8\r
-OPC_SBC_aby = $F9\r
-OPC_SBC_abx = $FD\r
-OPC_INC_abx = $FE\r
-\r
-\r
-.if (.cpu .bitand ::CPU_ISET_65SC02)\r
-\r
-; OPC_NOP   = $02               ; doublet\r
-; OPC_NOP   = $03               ; doublet\r
-OPC_TSB_zp  = $04\r
-; OPC_NOP   = $0B               ; doublet\r
-OPC_TSB_abs = $0C\r
-\r
-OPC_ORA_izp = $12\r
-; OPC_NOP   = $13               ; doublet\r
-OPC_TRB_zp  = $14\r
-OPC_INC     = $1A\r
-; OPC_NOP   = $1B               ; doublet\r
-OPC_TRB_abs = $1C\r
-\r
-; OPC_NOP   = $22               ; doublet\r
-; OPC_NOP   = $23               ; doublet\r
-; OPC_NOP   = $2B               ; doublet\r
-\r
-OPC_AND_izp = $32\r
-; OPC_NOP   = $33               ; doublet\r
-OPC_BIT_zpx = $34\r
-OPC_DEC     = $3A\r
-; OPC_NOP   = $3B               ; doublet\r
-OPC_BIT_abx = $3C\r
-\r
-; OPC_NOP   = $42               ; doublet\r
-; OPC_NOP   = $43               ; doublet\r
-; OPC_NOP   = $44               ; doublet\r
-; OPC_NOP   = $4B               ; doublet\r
-\r
-OPC_EOR_izp = $52               \r
-; OPC_NOP   = $53               ; doublet\r
-; OPC_NOP   = $54               ; doublet\r
-; OPC_NOP   = $5A               ; doublet\r
-; OPC_NOP   = $5B               ; doublet\r
-OPC_EOR_abx = $5C\r
-\r
-; OPC_NOP   = $62               ; doublet\r
-; OPC_NOP   = $63               ; doublet\r
-OPC_STZ_zp  = $64\r
-; OPC_NOP   = $6B               ; doublet\r
-\r
-OPC_ADC_izp = $72\r
-; OPC_NOP   = $73               ; doublet\r
-OPC_STZ_zpx = $74\r
-OPC_PLY     = $7A\r
-; OPC_NOP   = $7B               ; doublet\r
-OPC_JMP_iax = $7C\r
-\r
-OPC_BRA     = $80\r
-; OPC_NOP   = $82               ; doublet\r
-; OPC_NOP   = $83               ; doublet\r
-OPC_BIT_imm = $89\r
-; OPC_NOP   = $8B               ; doublet\r
-\r
-OPC_STA_izp = $92\r
-; OPC_NOP   = $93               ; doublet\r
-; OPC_NOP   = $9B               ; doublet\r
-OPC_STZ_abs = $9C\r
-OPC_STZ_abx = $9E\r
-\r
-; OPC_NOP   = $A3               ; doublet\r
-; OPC_NOP   = $AB               ; doublet\r
-\r
-OPC_LDA_izp = $B2\r
-; OPC_NOP   = $B3               ; doublet\r
-; OPC_NOP   = $BB               ; doublet\r
-\r
-; OPC_NOP   = $C2               ; doublet\r
-; OPC_NOP   = $C3               ; doublet\r
-; OPC_NOP   = $CB               ; doublet\r
-\r
-OPC_CMP_izp = $D2\r
-; OPC_NOP   = $D3               ; doublet\r
-; OPC_NOP   = $D4               ; doublet\r
-OPC_PHX     = $DA\r
-; OPC_NOP   = $DB               ; doublet\r
-; OPC_NOP   = $DC               ; doublet\r
-\r
-; OPC_NOP   = $E2               ; doublet\r
-; OPC_NOP   = $E3               ; doublet\r
-; OPC_NOP   = $EB               ; doublet\r
-\r
-OPC_SBC_izp = $F2\r
-; OPC_NOP   = $F3               ; doublet\r
-; OPC_NOP   = $F4               ; doublet\r
-OPC_PLX     = $FA\r
-; OPC_NOP   = $FB               ; doublet\r
-; OPC_NOP   = $FC               ; doublet\r
-\r
-\r
-.if (.cpu .bitand ::CPU_ISET_65C02)\r
-\r
-; bit instructions for 65C02\r
-\r
-OPC_RMB0    = $07\r
-OPC_RMB1    = $17\r
-OPC_RMB2    = $27\r
-OPC_RMB3    = $37\r
-OPC_RMB4    = $47\r
-OPC_RMB5    = $57\r
-OPC_RMB6    = $67\r
-OPC_RMB7    = $77\r
-\r
-OPC_SMB0    = $87\r
-OPC_SMB1    = $97\r
-OPC_SMB2    = $A7\r
-OPC_SMB3    = $B7\r
-OPC_SMB4    = $C7\r
-OPC_SMB5    = $D7\r
-OPC_SMB6    = $E7\r
-OPC_SMB7    = $F7\r
-\r
-OPC_BBR0    = $0F\r
-OPC_BBR1    = $1F\r
-OPC_BBR2    = $2F\r
-OPC_BBR3    = $3F\r
-OPC_BBR4    = $4F\r
-OPC_BBR5    = $5F\r
-OPC_BBR6    = $6F\r
-OPC_BBR7    = $7F\r
-\r
-OPC_BBS0    = $8F\r
-OPC_BBS1    = $9F\r
-OPC_BBS2    = $AF\r
-OPC_BBS3    = $BF\r
-OPC_BBS4    = $CF\r
-OPC_BBS5    = $DF\r
-OPC_BBS6    = $EF\r
-OPC_BBS7    = $FF\r
-\r
-.else\r
-\r
-; no bit instructions for 65SC02\r
-\r
-; OPC_NOP   = $07               ; doublet\r
-; OPC_NOP   = $17               ; doublet\r
-; OPC_NOP   = $27               ; doublet\r
-; OPC_NOP   = $37               ; doublet\r
-; OPC_NOP   = $47               ; doublet\r
-; OPC_NOP   = $57               ; doublet\r
-; OPC_NOP   = $67               ; doublet\r
-; OPC_NOP   = $77               ; doublet\r
-; OPC_NOP   = $87               ; doublet\r
-; OPC_NOP   = $97               ; doublet\r
-; OPC_NOP   = $A7               ; doublet\r
-; OPC_NOP   = $B7               ; doublet\r
-; OPC_NOP   = $C7               ; doublet\r
-; OPC_NOP   = $D7               ; doublet\r
-; OPC_NOP   = $E7               ; doublet\r
-; OPC_NOP   = $F7               ; doublet\r
-; OPC_NOP   = $0F               ; doublet\r
-; OPC_NOP   = $1F               ; doublet\r
-; OPC_NOP   = $2F               ; doublet\r
-; OPC_NOP   = $3F               ; doublet\r
-; OPC_NOP   = $4F               ; doublet\r
-; OPC_NOP   = $5F               ; doublet\r
-; OPC_NOP   = $6F               ; doublet\r
-; OPC_NOP   = $7F               ; doublet\r
-; OPC_NOP   = $8F               ; doublet\r
-; OPC_NOP   = $9F               ; doublet\r
-; OPC_NOP   = $AF               ; doublet\r
-; OPC_NOP   = $BF               ; doublet\r
-; OPC_NOP   = $CF               ; doublet\r
-; OPC_NOP   = $DF               ; doublet\r
-; OPC_NOP   = $EF               ; doublet\r
-; OPC_NOP   = $FF               ; doublet\r
-\r
-.endif\r
-\r
-.elseif (.cpu .bitand ::CPU_ISET_6502X)\r
-\r
-; stable, undocumented opcodes\r
-\r
-; OPC_KIL   = $02               ; unstable\r
-OPC_SLO_izx = $03\r
-OPC_NOP_zp  = $04\r
-OPC_SLO_zp  = $07\r
-OPC_ANC_imm = $0B\r
-OPC_NOP_abs = $0C\r
-OPC_SLO_abs = $0F\r
-\r
-; OPC_KIL   = $12               ; unstable\r
-OPC_SLO_izy = $13\r
-OPC_NOP_zpx = $14\r
-OPC_SLO_zpx = $17\r
-;OPC_NOP    = $1A\r
-OPC_SLO_aby = $1B\r
-OPC_NOP_abx = $1C\r
-OPC_SLO_abx = $1F\r
-\r
-; OPC_KIL   = $22               ; unstable\r
-OPC_RLA_izx = $23\r
-OPC_RLA_zp  = $27\r
-OPC_ANC_imm = $2B\r
-OPC_RLA_abs = $2F\r
-\r
-; OPC_KIL   = $32               ; unstable\r
-OPC_RLA_izy = $33\r
-OPC_NOP_zpx = $34\r
-OPC_RLA_zpx = $37\r
-; OPC_NOP   = $3A               ; doublet\r
-OPC_RLA_aby = $3B\r
-OPC_NOP_abx = $3C\r
-OPC_RLA_abx = $3F\r
-\r
-; OPC_KIL   = $42               ; unstable\r
-OPC_SRE_izx = $43\r
-OPC_NOP_zp  = $44\r
-OPC_SRE_zp  = $47\r
-OPC_ALR_imm = $4B\r
-OPC_SRE_abs = $4F\r
-\r
-; OPC_KIL   = $52               ; unstable\r
-OPC_SRE_izy = $53\r
-OPC_NOP_zpx = $54\r
-OPC_SRE_zpx = $57\r
-; OPC_NOP   = $5A               ; doublet\r
-OPC_SRE_aby = $5B\r
-OPC_NOP_abx = $5C\r
-OPC_SRE_abx = $5F\r
-\r
-; OPC_KIL   = $62\r
-OPC_RRA_izx = $63\r
-OPC_NOP_zp  = $64\r
-OPC_RRA_zp  = $67\r
-OPC_ARR_imm = $6B\r
-OPC_RRA_abs = $6F\r
-\r
-; OPC_KIL   = $72\r
-OPC_RRA_izy = $73\r
-OPC_NOP_zpx = $74\r
-OPC_RRA_zpx = $77\r
-; OPC_NOP   = $7A               ; doublet\r
-OPC_RRA_aby = $7B\r
-OPC_NOP_abx = $7C\r
-OPC_RRA_abx = $7F\r
-\r
-OPC_NOP_imm = $80\r
-; OPC_NOP_imm = $82             ; doublet\r
-OPC_SAX_izx = $83\r
-OPC_SAX_zp  = $87\r
-; OPC_NOP_imm = $89             ; doublet\r
-; OPC_XAA = $8B                 ; unstable\r
-OPC_SAX_abs = $8F\r
-\r
-; OPC_KIL   = $92               ; unstable\r
-; OPC_AHX_izy = $93             ; unstable\r
-OPC_SAX_zpy = $97\r
-; OPC_TAS_aby = $9B             ; unstable\r
-; OPC_SHY_abx = $9C             ; unstable\r
-; OPC_SHX_aby = $9E             ; unstable\r
-; OPC_AHX_aby = $9F             ; unstable\r
-\r
-OPC_LAX_izx = $A3\r
-OPC_LAX_zp  = $A7\r
-; OPC_LAX_imm = $AB             ; unstable\r
-OPC_LAX_abs = $AF\r
-\r
-; OPC_KIL   = $B2               ; unstable\r
-OPC_LAX_izy = $B3\r
-OPC_LAX_zpy = $B7\r
-OPC_LAS_aby = $BB\r
-OPC_LAX_aby = $BF\r
-\r
-; OPC_NOP_imm = $C2             ; doublet\r
-OPC_DCP_izx = $C3\r
-OPC_DCP_zp  = $C7\r
-OPC_AXS_imm = $CB\r
-OPC_DCP_abs = $CF\r
-\r
-; OPC_KIL   = $D2               ; unstable\r
-OPC_DCP_izy = $D3\r
-OPC_NOP_zpx = $D4\r
-OPC_DCP_zpx = $D7\r
-OPC_NOP_DA  = $DA\r
-OPC_DCP_aby = $DB\r
-OPC_NOP_abx = $DC\r
-OPC_DCP_abx = $DF\r
-\r
-; OPC_NOP_imm = $E2             ; doublet\r
-OPC_ISC_izx = $E3\r
-OPC_ISC_zp  = $E7\r
-; OPC_SBC_imm = $EB             ; doublet\r
-OPC_ISC_abs = $EF\r
-\r
-; OPC_KIL   = $F2               ; unstable\r
-OPC_ISC_izy = $F3\r
-OPC_NOP_zpx = $F4\r
-OPC_ISC_zpx = $F7\r
-OPC_NOP_FA  = $FA\r
-OPC_ISC_aby = $FB\r
-OPC_NOP_abx = $FC\r
-OPC_ISC_abx = $FF\r
-\r
-.endif\r
+; opcodes.inc
+; ca65 6502 - opcode definitions, mainly for self modifying code
+;
+; Christian Krüger, latest change: 18-Sep-2010
+;
+; This software is provided 'as-is', without any expressed or implied      
+; warranty.  In no event will the authors be held liable for any damages   
+; arising from the use of this software.                                   
+;                                                                          
+; Permission is granted to anyone to use this software for any purpose,    
+; including commercial applications, and to alter it and redistribute it   
+; freely, subject to the following restrictions:                           
+;                                                                          
+; 1. The origin of this software must not be misrepresented; you must not  
+;    claim that you wrote the original software. If you use this software  
+;    in a product, an acknowledgment in the product documentation would be 
+;    appreciated but is not required.                                      
+; 2. Altered source versions must be plainly marked as such, and must not  
+;    be misrepresented as being the original software.                     
+; 3. This notice may not be removed or altered from any source             
+;    distribution.                                                         
+;                                                                          
+
+; Opcode-Table
+; ------------
+; Post fix explanation:
+; imm = #$00
+; zp = $00
+; zpx = $00,X
+; zpy = $00,Y
+; izp = ($00)
+; izx = ($00,X)
+; izy = ($00),Y
+; abs = $0000
+; abx = $0000,X
+; aby = $0000,Y
+; ind = ($0000)
+; iax = ($0000,X)
+; rel = $0000 (PC-relative) (supressed here)
+
+.macpack        cpu
+
+OPC_BRK     = $00
+OPC_ORA_izx = $01
+OPC_ORA_zp  = $05
+OPC_ASL_zp  = $06
+OPC_PHP     = $08
+OPC_ORA_imm = $09
+OPC_ASL     = $0A
+OPC_ORA_abs = $0D
+OPC_ASL_abs = $0E
+
+OPC_BPL     = $10
+OPC_ORA_izy = $11
+OPC_ORA_zpx = $15
+OPC_ASL_zpx = $16
+OPC_CLC     = $18
+OPC_ORA_aby = $19
+OPC_ORA_abx = $1D
+OPC_ASL_abx = $1E
+
+OPC_JSR_abs = $20
+OPC_AND_izx = $21
+OPC_BIT_zp  = $24
+OPC_AND_zp  = $25
+OPC_ROL_zp  = $26
+OPC_PLP     = $28
+OPC_AND_imm = $29
+OPC_ROL     = $2A
+OPC_BIT_abs = $2C
+OPC_AND_abs = $2D
+OPC_ROL_abs = $2E
+
+OPC_BMI     = $30
+OPC_AND_izy = $31
+OPC_AND_zpx = $35
+OPC_ROL_zpx = $36
+OPC_SEC     = $38
+OPC_AND_aby = $39
+OPC_AND_abx = $3D
+OPC_ROL_abx = $3E
+
+
+OPC_RTI     = $40
+OPC_EOR_izx = $41
+OPC_EOR_zp  = $45
+OPC_LSR_zp  = $46
+OPC_PHA     = $48
+OPC_EOR_imm = $49
+OPC_LSR     = $4A
+OPC_JMP_abs = $4C
+OPC_EOR_abs = $4D
+OPC_LSR_abs = $4E
+
+OPC_BVC     = $50
+OPC_EOR_izy = $51
+OPC_EOR_zpx = $55
+OPC_LSR_zpx = $56
+OPC_CLI     = $58
+OPC_EOR_aby = $59
+OPC_EOR_abx = $5D
+OPC_LSR_abx = $5E
+
+OPC_RTS     = $60
+OPC_ADC_izx = $61
+OPC_ADC_zp  = $65
+OPC_ROR_zp  = $66
+OPC_PLA     = $68
+OPC_ADC_imm = $69
+OPC_ROR     = $6A
+OPC_JMP_ind = $6C
+OPC_ADC_abs = $6D
+OPC_ROR_abs = $6E
+
+OPC_BVS     = $70
+OPC_ADC_izy = $71
+OPC_ADC_zpx = $75
+OPC_ROR_zpx = $76
+OPC_SEI     = $78
+OPC_ADC_aby = $79
+OPC_ADC_abx = $7D
+OPC_ROR_abx = $7E
+
+OPC_STA_izx = $81
+OPC_STY_zp  = $84
+OPC_STA_zp  = $85
+OPC_STX_zp  = $86
+OPC_DEY     = $88
+OPC_TXA     = $8A
+OPC_STY_abs = $8C
+OPC_STA_abs = $8D
+OPC_STX_abs = $8E
+
+OPC_BCC     = $90
+OPC_STA_izy = $91
+OPC_STY_zpx = $94
+OPC_STA_zpx = $95
+OPC_STX_zpy = $96
+OPC_TYA     = $98
+OPC_STA_aby = $99
+OPC_TXS     = $9A
+OPC_STA_abx = $9D
+
+OPC_LDY_imm = $A0
+OPC_LDA_izx = $A1
+OPC_LDX_imm = $A2
+OPC_LDY_zp  = $A4
+OPC_LDA_zp  = $A5
+OPC_LDX_zp  = $A6
+OPC_TAY     = $A8
+OPC_LDA_imm = $A9
+OPC_TAX     = $AA
+OPC_LDY_abs = $AC
+OPC_LDA_abs = $AD
+OPC_LDX_abs = $AE
+
+OPC_BCS     = $B0
+OPC_LDA_izy = $B1
+OPC_LDY_zpx = $B4
+OPC_LDA_zpx = $B5
+OPC_LDX_zpy = $B6
+OPC_CLV     = $B8
+OPC_LDA_aby = $B9
+OPC_TSX     = $BA
+OPC_LDY_abx = $BC
+OPC_LDA_abx = $BD
+OPC_LDX_aby = $BE
+
+OPC_CPY_imm = $C0
+OPC_CMP_izx = $C1
+OPC_CPY_zp  = $C4
+OPC_CMP_zp  = $C5
+OPC_DEC_zp  = $C6
+OPC_INY     = $C8
+OPC_CMP_imm = $C9
+OPC_DEX     = $CA
+OPC_CPY_abs = $CC
+OPC_CMP_abs = $CD
+OPC_DEC_abs = $CE
+
+OPC_BNE     = $D0
+OPC_CMP_izy = $D1
+OPC_CMP_zpx = $D5
+OPC_DEC_zpx = $D6
+OPC_CLD     = $D8
+OPC_CMP_aby = $D9
+OPC_CMP_abx = $DD
+OPC_DEC_abx = $DE
+
+OPC_CPX_imm = $E0
+OPC_SBC_izx = $E1
+OPC_CPX_zp  = $E4
+OPC_SBC_zp  = $E5
+OPC_INC_zp  = $E6
+OPC_INX     = $E8
+OPC_SBC_imm = $E9
+OPC_NOP     = $EA
+OPC_CPX_abs = $EC
+OPC_SBC_abs = $ED
+OPC_INC_abs = $EE
+
+
+OPC_BEQ     = $F0
+OPC_SBC_izy = $F1
+OPC_SBC_zpx = $F5
+OPC_INC_zpx = $F6
+OPC_SED     = $F8
+OPC_SBC_aby = $F9
+OPC_SBC_abx = $FD
+OPC_INC_abx = $FE
+
+
+.if (.cpu .bitand ::CPU_ISET_65SC02)
+
+; OPC_NOP   = $02               ; doublet
+; OPC_NOP   = $03               ; doublet
+OPC_TSB_zp  = $04
+; OPC_NOP   = $0B               ; doublet
+OPC_TSB_abs = $0C
+
+OPC_ORA_izp = $12
+; OPC_NOP   = $13               ; doublet
+OPC_TRB_zp  = $14
+OPC_INC     = $1A
+; OPC_NOP   = $1B               ; doublet
+OPC_TRB_abs = $1C
+
+; OPC_NOP   = $22               ; doublet
+; OPC_NOP   = $23               ; doublet
+; OPC_NOP   = $2B               ; doublet
+
+OPC_AND_izp = $32
+; OPC_NOP   = $33               ; doublet
+OPC_BIT_zpx = $34
+OPC_DEC     = $3A
+; OPC_NOP   = $3B               ; doublet
+OPC_BIT_abx = $3C
+
+; OPC_NOP   = $42               ; doublet
+; OPC_NOP   = $43               ; doublet
+; OPC_NOP   = $44               ; doublet
+; OPC_NOP   = $4B               ; doublet
+
+OPC_EOR_izp = $52               
+; OPC_NOP   = $53               ; doublet
+; OPC_NOP   = $54               ; doublet
+; OPC_NOP   = $5A               ; doublet
+; OPC_NOP   = $5B               ; doublet
+OPC_EOR_abx = $5C
+
+; OPC_NOP   = $62               ; doublet
+; OPC_NOP   = $63               ; doublet
+OPC_STZ_zp  = $64
+; OPC_NOP   = $6B               ; doublet
+
+OPC_ADC_izp = $72
+; OPC_NOP   = $73               ; doublet
+OPC_STZ_zpx = $74
+OPC_PLY     = $7A
+; OPC_NOP   = $7B               ; doublet
+OPC_JMP_iax = $7C
+
+OPC_BRA     = $80
+; OPC_NOP   = $82               ; doublet
+; OPC_NOP   = $83               ; doublet
+OPC_BIT_imm = $89
+; OPC_NOP   = $8B               ; doublet
+
+OPC_STA_izp = $92
+; OPC_NOP   = $93               ; doublet
+; OPC_NOP   = $9B               ; doublet
+OPC_STZ_abs = $9C
+OPC_STZ_abx = $9E
+
+; OPC_NOP   = $A3               ; doublet
+; OPC_NOP   = $AB               ; doublet
+
+OPC_LDA_izp = $B2
+; OPC_NOP   = $B3               ; doublet
+; OPC_NOP   = $BB               ; doublet
+
+; OPC_NOP   = $C2               ; doublet
+; OPC_NOP   = $C3               ; doublet
+; OPC_NOP   = $CB               ; doublet
+
+OPC_CMP_izp = $D2
+; OPC_NOP   = $D3               ; doublet
+; OPC_NOP   = $D4               ; doublet
+OPC_PHX     = $DA
+; OPC_NOP   = $DB               ; doublet
+; OPC_NOP   = $DC               ; doublet
+
+; OPC_NOP   = $E2               ; doublet
+; OPC_NOP   = $E3               ; doublet
+; OPC_NOP   = $EB               ; doublet
+
+OPC_SBC_izp = $F2
+; OPC_NOP   = $F3               ; doublet
+; OPC_NOP   = $F4               ; doublet
+OPC_PLX     = $FA
+; OPC_NOP   = $FB               ; doublet
+; OPC_NOP   = $FC               ; doublet
+
+
+.if (.cpu .bitand ::CPU_ISET_65C02)
+
+; bit instructions for 65C02
+
+OPC_RMB0    = $07
+OPC_RMB1    = $17
+OPC_RMB2    = $27
+OPC_RMB3    = $37
+OPC_RMB4    = $47
+OPC_RMB5    = $57
+OPC_RMB6    = $67
+OPC_RMB7    = $77
+
+OPC_SMB0    = $87
+OPC_SMB1    = $97
+OPC_SMB2    = $A7
+OPC_SMB3    = $B7
+OPC_SMB4    = $C7
+OPC_SMB5    = $D7
+OPC_SMB6    = $E7
+OPC_SMB7    = $F7
+
+OPC_BBR0    = $0F
+OPC_BBR1    = $1F
+OPC_BBR2    = $2F
+OPC_BBR3    = $3F
+OPC_BBR4    = $4F
+OPC_BBR5    = $5F
+OPC_BBR6    = $6F
+OPC_BBR7    = $7F
+
+OPC_BBS0    = $8F
+OPC_BBS1    = $9F
+OPC_BBS2    = $AF
+OPC_BBS3    = $BF
+OPC_BBS4    = $CF
+OPC_BBS5    = $DF
+OPC_BBS6    = $EF
+OPC_BBS7    = $FF
+
+.else
+
+; no bit instructions for 65SC02
+
+; OPC_NOP   = $07               ; doublet
+; OPC_NOP   = $17               ; doublet
+; OPC_NOP   = $27               ; doublet
+; OPC_NOP   = $37               ; doublet
+; OPC_NOP   = $47               ; doublet
+; OPC_NOP   = $57               ; doublet
+; OPC_NOP   = $67               ; doublet
+; OPC_NOP   = $77               ; doublet
+; OPC_NOP   = $87               ; doublet
+; OPC_NOP   = $97               ; doublet
+; OPC_NOP   = $A7               ; doublet
+; OPC_NOP   = $B7               ; doublet
+; OPC_NOP   = $C7               ; doublet
+; OPC_NOP   = $D7               ; doublet
+; OPC_NOP   = $E7               ; doublet
+; OPC_NOP   = $F7               ; doublet
+; OPC_NOP   = $0F               ; doublet
+; OPC_NOP   = $1F               ; doublet
+; OPC_NOP   = $2F               ; doublet
+; OPC_NOP   = $3F               ; doublet
+; OPC_NOP   = $4F               ; doublet
+; OPC_NOP   = $5F               ; doublet
+; OPC_NOP   = $6F               ; doublet
+; OPC_NOP   = $7F               ; doublet
+; OPC_NOP   = $8F               ; doublet
+; OPC_NOP   = $9F               ; doublet
+; OPC_NOP   = $AF               ; doublet
+; OPC_NOP   = $BF               ; doublet
+; OPC_NOP   = $CF               ; doublet
+; OPC_NOP   = $DF               ; doublet
+; OPC_NOP   = $EF               ; doublet
+; OPC_NOP   = $FF               ; doublet
+
+.endif
+
+.elseif (.cpu .bitand ::CPU_ISET_6502X)
+
+; stable, undocumented opcodes
+
+; OPC_KIL   = $02               ; unstable
+OPC_SLO_izx = $03
+OPC_NOP_zp  = $04
+OPC_SLO_zp  = $07
+OPC_ANC_imm = $0B
+OPC_NOP_abs = $0C
+OPC_SLO_abs = $0F
+
+; OPC_KIL   = $12               ; unstable
+OPC_SLO_izy = $13
+OPC_NOP_zpx = $14
+OPC_SLO_zpx = $17
+;OPC_NOP    = $1A
+OPC_SLO_aby = $1B
+OPC_NOP_abx = $1C
+OPC_SLO_abx = $1F
+
+; OPC_KIL   = $22               ; unstable
+OPC_RLA_izx = $23
+OPC_RLA_zp  = $27
+OPC_ANC_imm = $2B
+OPC_RLA_abs = $2F
+
+; OPC_KIL   = $32               ; unstable
+OPC_RLA_izy = $33
+OPC_NOP_zpx = $34
+OPC_RLA_zpx = $37
+; OPC_NOP   = $3A               ; doublet
+OPC_RLA_aby = $3B
+OPC_NOP_abx = $3C
+OPC_RLA_abx = $3F
+
+; OPC_KIL   = $42               ; unstable
+OPC_SRE_izx = $43
+OPC_NOP_zp  = $44
+OPC_SRE_zp  = $47
+OPC_ALR_imm = $4B
+OPC_SRE_abs = $4F
+
+; OPC_KIL   = $52               ; unstable
+OPC_SRE_izy = $53
+OPC_NOP_zpx = $54
+OPC_SRE_zpx = $57
+; OPC_NOP   = $5A               ; doublet
+OPC_SRE_aby = $5B
+OPC_NOP_abx = $5C
+OPC_SRE_abx = $5F
+
+; OPC_KIL   = $62
+OPC_RRA_izx = $63
+OPC_NOP_zp  = $64
+OPC_RRA_zp  = $67
+OPC_ARR_imm = $6B
+OPC_RRA_abs = $6F
+
+; OPC_KIL   = $72
+OPC_RRA_izy = $73
+OPC_NOP_zpx = $74
+OPC_RRA_zpx = $77
+; OPC_NOP   = $7A               ; doublet
+OPC_RRA_aby = $7B
+OPC_NOP_abx = $7C
+OPC_RRA_abx = $7F
+
+OPC_NOP_imm = $80
+; OPC_NOP_imm = $82             ; doublet
+OPC_SAX_izx = $83
+OPC_SAX_zp  = $87
+; OPC_NOP_imm = $89             ; doublet
+; OPC_XAA = $8B                 ; unstable
+OPC_SAX_abs = $8F
+
+; OPC_KIL   = $92               ; unstable
+; OPC_AHX_izy = $93             ; unstable
+OPC_SAX_zpy = $97
+; OPC_TAS_aby = $9B             ; unstable
+; OPC_SHY_abx = $9C             ; unstable
+; OPC_SHX_aby = $9E             ; unstable
+; OPC_AHX_aby = $9F             ; unstable
+
+OPC_LAX_izx = $A3
+OPC_LAX_zp  = $A7
+; OPC_LAX_imm = $AB             ; unstable
+OPC_LAX_abs = $AF
+
+; OPC_KIL   = $B2               ; unstable
+OPC_LAX_izy = $B3
+OPC_LAX_zpy = $B7
+OPC_LAS_aby = $BB
+OPC_LAX_aby = $BF
+
+; OPC_NOP_imm = $C2             ; doublet
+OPC_DCP_izx = $C3
+OPC_DCP_zp  = $C7
+OPC_AXS_imm = $CB
+OPC_DCP_abs = $CF
+
+; OPC_KIL   = $D2               ; unstable
+OPC_DCP_izy = $D3
+OPC_NOP_zpx = $D4
+OPC_DCP_zpx = $D7
+OPC_NOP_DA  = $DA
+OPC_DCP_aby = $DB
+OPC_NOP_abx = $DC
+OPC_DCP_abx = $DF
+
+; OPC_NOP_imm = $E2             ; doublet
+OPC_ISC_izx = $E3
+OPC_ISC_zp  = $E7
+; OPC_SBC_imm = $EB             ; doublet
+OPC_ISC_abs = $EF
+
+; OPC_KIL   = $F2               ; unstable
+OPC_ISC_izy = $F3
+OPC_NOP_zpx = $F4
+OPC_ISC_zpx = $F7
+OPC_NOP_FA  = $FA
+OPC_ISC_aby = $FB
+OPC_NOP_abx = $FC
+OPC_ISC_abx = $FF
+
+.endif
index d5752a5f5cb17ed1211d63b47ec85114005f93c7..0583f79e0ba97a3eea7e0e7b2cf9b033fedb1a70 100644 (file)
-; smc.mac\r
-; ca65 Macro-Pack for Self Modifying Code (SMC)\r
-;\r
-; (c) Christian Krüger, latest change: 17-Jul-2016\r
-;\r
-; This software is provided 'as-is', without any expressed or implied\r
-; warranty.  In no event will the authors be held liable for any damages\r
-; arising from the use of this software.\r
-;\r
-; Permission is granted to anyone to use this software for any purpose,\r
-; including commercial applications, and to alter it and redistribute it\r
-; freely, subject to the following restrictions:\r
-;\r
-; 1. The origin of this software must not be misrepresented; you must not\r
-;    claim that you wrote the original software. If you use this software\r
-;    in a product, an acknowledgment in the product documentation would be\r
-;    appreciated but is not required.\r
-; 2. Altered source versions must be plainly marked as such, and must not\r
-;    be misrepresented as being the original software.\r
-; 3. This notice may not be removed or altered from any source\r
-;    distribution.\r
-;\r
-\r
-.define _SMCDesignator  .mid(0, .tcount(label) - 1, label) .ident(.concat(.string(.right(1, label)), "_SMC"))\r
-.define _SMCAlias       .mid(0, .tcount(alias) - 1, alias) .ident(.concat(.string(.right(1, alias)), "_SMC"))\r
-.define SMC_AbsAdr      $FADE\r
-.define SMC_ZpAdr       $00\r
-.define SMC_Opcode      nop\r
-.define SMC_Value       $42\r
-\r
-.macro SMC_OperateOnValue opcode, label\r
-        opcode _SMCDesignator+1\r
-.endmacro\r
-\r
-.macro SMC_OperateOnLowByte opcode, label\r
-        SMC_OperateOnValue opcode, label\r
-.endmacro\r
-\r
-.macro SMC_OperateOnHighByte opcode, label\r
-        opcode _SMCDesignator + 2\r
-.endmacro\r
-\r
-.macro SMC_Import alias\r
-.import _SMCAlias\r
-.endmacro\r
-\r
-.macro SMC_Export alias, label\r
-.export _SMCAlias := _SMCDesignator\r
-.endmacro\r
-\r
-.macro  SMC     label, statement\r
-_SMCDesignator: statement\r
-.endmacro\r
-\r
-.macro SMC_TransferOpcode       label, opcode, register\r
-.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
-        lda #opcode\r
-        sta _SMCDesignator\r
-.elseif .match ({register}, x)\r
-        ldx #opcode\r
-        stx _SMCDesignator\r
-.elseif .match ({register}, y)\r
-        ldy #opcode\r
-        sty _SMCDesignator\r
-.else\r
-       .error "Invalid usage of macro 'SMC_TransferOpcode'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_LoadOpcode   label, register\r
-.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
-        lda _SMCDesignator\r
-.elseif .match ({register}, x)\r
-        ldx _SMCDesignator\r
-.elseif .match ({register}, y)\r
-        ldy _SMCDesignator\r
-.else\r
-       .error "Invalid usage of macro 'SMC_LoadOpcode'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_StoreOpcode  label, register\r
-.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
-        sta _SMCDesignator\r
-.elseif .match ({register}, x)\r
-        stx _SMCDesignator\r
-.elseif .match ({register}, y)\r
-        sty _SMCDesignator\r
-.else\r
-       .error "Invalid usage of macro 'SMC_StoreOpcode'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_ChangeBranch         label, destination, register\r
-.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
-        lda #(<(destination - _SMCDesignator -2))\r
-        sta _SMCDesignator+1\r
-.elseif .match ({register}, x)\r
-        ldx #(<(destination - _SMCDesignator - 2))\r
-        stx _SMCDesignator+1\r
-.elseif .match ({register}, y)\r
-        ldy #(<(destination - _SMCDesignator - 2))\r
-        sty _SMCDesignator+1\r
-.else\r
-       .error "Invalid usage of macro 'SMC_ChangeBranch'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_TransferValue        label, value, register\r
-.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
-        lda value\r
-        sta _SMCDesignator+1\r
-.elseif .match ({register}, x)\r
-        ldx value\r
-        stx _SMCDesignator+1\r
-.elseif .match ({register}, y)\r
-        ldy value\r
-        sty _SMCDesignator+1\r
-.else\r
-       .error "Invalid usage of macro 'SMC_TransferValue'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_LoadValue    label, register\r
-.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
-        lda _SMCDesignator+1\r
-.elseif .match ({register}, x)\r
-        ldx _SMCDesignator+1\r
-.elseif .match ({register}, y)\r
-        ldy _SMCDesignator+1\r
-.else\r
-       .error "Invalid usage of macro 'SMC_LoadValue'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_StoreValue   label, register\r
-.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
-        sta _SMCDesignator+1\r
-.elseif .match ({register}, x)\r
-        stx _SMCDesignator+1\r
-.elseif .match ({register}, y)\r
-        sty _SMCDesignator+1\r
-.else\r
-       .error "Invalid usage of macro 'SMC_StoreValue'"\r
-.endif\r
-.endmacro\r
-\r
-\r
-.macro SMC_TransferLowByte      label, value, register\r
-SMC_TransferValue label, value, register\r
-.endmacro\r
-\r
-.macro SMC_LoadLowByte  label, register\r
-SMC_LoadValue label, register\r
-.endmacro\r
-\r
-.macro SMC_StoreLowByte label, register\r
-SMC_StoreValue label, register\r
-.endmacro\r
-\r
-.macro SMC_TransferHighByte     label, value, register\r
-.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )\r
-        lda value\r
-        sta _SMCDesignator+2\r
-.elseif .match ({register}, x)\r
-        ldx value\r
-        stx _SMCDesignator+2\r
-.elseif .match ({register}, y)\r
-        ldy value\r
-        sty _SMCDesignator+2\r
-.else\r
-       .error "Invalid usage of macro 'SMC_TransferHighByte'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_LoadHighByte label, register\r
-.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
-        lda _SMCDesignator+2\r
-.elseif .match ({register}, x)\r
-        ldx _SMCDesignator+2\r
-.elseif .match ({register}, y)\r
-        ldy _SMCDesignator+2\r
-.else\r
-       .error "Invalid usage of macro 'SMC_LoadHighByte'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_StoreHighByte        label, register\r
-.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )\r
-        sta _SMCDesignator+2\r
-.elseif .match ({register}, x)\r
-        stx _SMCDesignator+2\r
-.elseif .match ({register}, y)\r
-        sty _SMCDesignator+2\r
-.else\r
-       .error "Invalid usage of macro 'SMC_StoreHighByte'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_TransferAddressSingle        label, address, register\r
-.if .paramcount = 2 .or .match ((register), a) .or .match ({register}, )\r
-        .if (.match (.left (1, {address}), #))\r
-                ; immediate mode\r
-                lda #<(.right (.tcount ({address})-1, {address}))\r
-                sta _SMCDesignator+1\r
-                lda #>(.right (.tcount ({address})-1, {address}))\r
-                sta _SMCDesignator+2\r
-        .else\r
-                ; assume absolute or zero page\r
-                lda address\r
-                sta _SMCDesignator+1\r
-                lda 1+(address)\r
-                sta _SMCDesignator+2\r
-        .endif\r
-.elseif .match ((register), x)\r
-        .if (.match (.left (1, {address}), #))\r
-                ; immediate mode\r
-                ldx #<(.right (.tcount ({address})-1, {address}))\r
-                stx _SMCDesignator+1\r
-                ldx #>(.right (.tcount ({address})-1, {address}))\r
-                stx _SMCDesignator+2\r
-        .else\r
-                ; assume absolute or zero page\r
-                ldx address\r
-                stx _SMCDesignator+1\r
-                ldx 1+(address)\r
-                stx _SMCDesignator+2\r
-        .endif\r
-.elseif .match ((register), y)\r
-        .if (.match (.left (1, {address}), #))\r
-                ; immediate mode\r
-                ldy #<(.right (.tcount ({address})-1, {address}))\r
-                sty _SMCDesignator+1\r
-                ldy #>(.right (.tcount ({address})-1, {address}))\r
-                sty _SMCDesignator+2\r
-        .else\r
-                ; assume absolute or zero page\r
-                ldy address\r
-                sty _SMCDesignator+1\r
-                ldy 1+(address)\r
-                sty _SMCDesignator+2\r
-        .endif\r
-.else\r
-       .error "Invalid usage of macro 'SMC_TransferAddressSingle'"\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_TransferAddress      label, address\r
-.if (.match (.left (1, {address}), #))\r
-        ; immediate mode\r
-        lda #<(.right (.tcount ({address})-1, {address}))\r
-        sta _SMCDesignator+1\r
-        ldx #>(.right (.tcount ({address})-1, {address}))\r
-        stx _SMCDesignator+2\r
-.else\r
-        ; assume absolute or zero page\r
-        lda {address}\r
-        sta _SMCDesignator+1\r
-        ldx 1+{address}\r
-        stx _SMCDesignator)+2\r
-.endif\r
-.endmacro\r
-\r
-.macro SMC_StoreAddress label\r
-        sta _SMCDesignator+1\r
-        stx _SMCDesignator+2\r
-.endmacro\r
+; smc.mac
+; ca65 Macro-Pack for Self Modifying Code (SMC)
+;
+; (c) Christian Krüger, latest change: 17-Jul-2016
+;
+; This software is provided 'as-is', without any expressed or implied
+; warranty.  In no event will the authors be held liable for any damages
+; arising from the use of this software.
+;
+; Permission is granted to anyone to use this software for any purpose,
+; including commercial applications, and to alter it and redistribute it
+; freely, subject to the following restrictions:
+;
+; 1. The origin of this software must not be misrepresented; you must not
+;    claim that you wrote the original software. If you use this software
+;    in a product, an acknowledgment in the product documentation would be
+;    appreciated but is not required.
+; 2. Altered source versions must be plainly marked as such, and must not
+;    be misrepresented as being the original software.
+; 3. This notice may not be removed or altered from any source
+;    distribution.
+;
+
+.define _SMCDesignator  .mid(0, .tcount(label) - 1, label) .ident(.concat(.string(.right(1, label)), "_SMC"))
+.define _SMCAlias       .mid(0, .tcount(alias) - 1, alias) .ident(.concat(.string(.right(1, alias)), "_SMC"))
+.define SMC_AbsAdr      $FADE
+.define SMC_ZpAdr       $00
+.define SMC_Opcode      nop
+.define SMC_Value       $42
+
+.macro SMC_OperateOnValue opcode, label
+        opcode _SMCDesignator+1
+.endmacro
+
+.macro SMC_OperateOnLowByte opcode, label
+        SMC_OperateOnValue opcode, label
+.endmacro
+
+.macro SMC_OperateOnHighByte opcode, label
+        opcode _SMCDesignator + 2
+.endmacro
+
+.macro SMC_Import alias
+.import _SMCAlias
+.endmacro
+
+.macro SMC_Export alias, label
+.export _SMCAlias := _SMCDesignator
+.endmacro
+
+.macro  SMC     label, statement
+_SMCDesignator: statement
+.endmacro
+
+.macro SMC_TransferOpcode       label, opcode, register
+.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
+        lda #opcode
+        sta _SMCDesignator
+.elseif .match ({register}, x)
+        ldx #opcode
+        stx _SMCDesignator
+.elseif .match ({register}, y)
+        ldy #opcode
+        sty _SMCDesignator
+.else
+       .error "Invalid usage of macro 'SMC_TransferOpcode'"
+.endif
+.endmacro
+
+.macro SMC_LoadOpcode   label, register
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
+        lda _SMCDesignator
+.elseif .match ({register}, x)
+        ldx _SMCDesignator
+.elseif .match ({register}, y)
+        ldy _SMCDesignator
+.else
+       .error "Invalid usage of macro 'SMC_LoadOpcode'"
+.endif
+.endmacro
+
+.macro SMC_StoreOpcode  label, register
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
+        sta _SMCDesignator
+.elseif .match ({register}, x)
+        stx _SMCDesignator
+.elseif .match ({register}, y)
+        sty _SMCDesignator
+.else
+       .error "Invalid usage of macro 'SMC_StoreOpcode'"
+.endif
+.endmacro
+
+.macro SMC_ChangeBranch         label, destination, register
+.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
+        lda #(<(destination - _SMCDesignator -2))
+        sta _SMCDesignator+1
+.elseif .match ({register}, x)
+        ldx #(<(destination - _SMCDesignator - 2))
+        stx _SMCDesignator+1
+.elseif .match ({register}, y)
+        ldy #(<(destination - _SMCDesignator - 2))
+        sty _SMCDesignator+1
+.else
+       .error "Invalid usage of macro 'SMC_ChangeBranch'"
+.endif
+.endmacro
+
+.macro SMC_TransferValue        label, value, register
+.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
+        lda value
+        sta _SMCDesignator+1
+.elseif .match ({register}, x)
+        ldx value
+        stx _SMCDesignator+1
+.elseif .match ({register}, y)
+        ldy value
+        sty _SMCDesignator+1
+.else
+       .error "Invalid usage of macro 'SMC_TransferValue'"
+.endif
+.endmacro
+
+.macro SMC_LoadValue    label, register
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
+        lda _SMCDesignator+1
+.elseif .match ({register}, x)
+        ldx _SMCDesignator+1
+.elseif .match ({register}, y)
+        ldy _SMCDesignator+1
+.else
+       .error "Invalid usage of macro 'SMC_LoadValue'"
+.endif
+.endmacro
+
+.macro SMC_StoreValue   label, register
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
+        sta _SMCDesignator+1
+.elseif .match ({register}, x)
+        stx _SMCDesignator+1
+.elseif .match ({register}, y)
+        sty _SMCDesignator+1
+.else
+       .error "Invalid usage of macro 'SMC_StoreValue'"
+.endif
+.endmacro
+
+
+.macro SMC_TransferLowByte      label, value, register
+SMC_TransferValue label, value, register
+.endmacro
+
+.macro SMC_LoadLowByte  label, register
+SMC_LoadValue label, register
+.endmacro
+
+.macro SMC_StoreLowByte label, register
+SMC_StoreValue label, register
+.endmacro
+
+.macro SMC_TransferHighByte     label, value, register
+.if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, )
+        lda value
+        sta _SMCDesignator+2
+.elseif .match ({register}, x)
+        ldx value
+        stx _SMCDesignator+2
+.elseif .match ({register}, y)
+        ldy value
+        sty _SMCDesignator+2
+.else
+       .error "Invalid usage of macro 'SMC_TransferHighByte'"
+.endif
+.endmacro
+
+.macro SMC_LoadHighByte label, register
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
+        lda _SMCDesignator+2
+.elseif .match ({register}, x)
+        ldx _SMCDesignator+2
+.elseif .match ({register}, y)
+        ldy _SMCDesignator+2
+.else
+       .error "Invalid usage of macro 'SMC_LoadHighByte'"
+.endif
+.endmacro
+
+.macro SMC_StoreHighByte        label, register
+.if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, )
+        sta _SMCDesignator+2
+.elseif .match ({register}, x)
+        stx _SMCDesignator+2
+.elseif .match ({register}, y)
+        sty _SMCDesignator+2
+.else
+       .error "Invalid usage of macro 'SMC_StoreHighByte'"
+.endif
+.endmacro
+
+.macro SMC_TransferAddressSingle        label, address, register
+.if .paramcount = 2 .or .match ((register), a) .or .match ({register}, )
+        .if (.match (.left (1, {address}), #))
+                ; immediate mode
+                lda #<(.right (.tcount ({address})-1, {address}))
+                sta _SMCDesignator+1
+                lda #>(.right (.tcount ({address})-1, {address}))
+                sta _SMCDesignator+2
+        .else
+                ; assume absolute or zero page
+                lda address
+                sta _SMCDesignator+1
+                lda 1+(address)
+                sta _SMCDesignator+2
+        .endif
+.elseif .match ((register), x)
+        .if (.match (.left (1, {address}), #))
+                ; immediate mode
+                ldx #<(.right (.tcount ({address})-1, {address}))
+                stx _SMCDesignator+1
+                ldx #>(.right (.tcount ({address})-1, {address}))
+                stx _SMCDesignator+2
+        .else
+                ; assume absolute or zero page
+                ldx address
+                stx _SMCDesignator+1
+                ldx 1+(address)
+                stx _SMCDesignator+2
+        .endif
+.elseif .match ((register), y)
+        .if (.match (.left (1, {address}), #))
+                ; immediate mode
+                ldy #<(.right (.tcount ({address})-1, {address}))
+                sty _SMCDesignator+1
+                ldy #>(.right (.tcount ({address})-1, {address}))
+                sty _SMCDesignator+2
+        .else
+                ; assume absolute or zero page
+                ldy address
+                sty _SMCDesignator+1
+                ldy 1+(address)
+                sty _SMCDesignator+2
+        .endif
+.else
+       .error "Invalid usage of macro 'SMC_TransferAddressSingle'"
+.endif
+.endmacro
+
+.macro SMC_TransferAddress      label, address
+.if (.match (.left (1, {address}), #))
+        ; immediate mode
+        lda #<(.right (.tcount ({address})-1, {address}))
+        sta _SMCDesignator+1
+        ldx #>(.right (.tcount ({address})-1, {address}))
+        stx _SMCDesignator+2
+.else
+        ; assume absolute or zero page
+        lda {address}
+        sta _SMCDesignator+1
+        ldx 1+{address}
+        stx _SMCDesignator)+2
+.endif
+.endmacro
+
+.macro SMC_StoreAddress label
+        sta _SMCDesignator+1
+        stx _SMCDesignator+2
+.endmacro
index 2c3502ba8821a0f769cdcabd93ecfb61d25fe983..8a51e1c32a3894a97a31ff2c9dd0fe6753e9ec99 100644 (file)
@@ -107,6 +107,7 @@ XWR0             = $10
 XWSTR0           = $14 
 XTEXT            = $19
 XHIRES           = $1A
+XFILLM           = $1C
 XMINMA           = $1F
 XFREAD           = $27          ; only in TELEMON 3.0
 XOPEN            = $30          ; only in TELEMON 3.0
@@ -128,6 +129,13 @@ XINK             = $93
 XEXPLO           = $9C 
 XPING            = $9D
 
+; ---------------------------------------------------------------------------
+; Page $200
+SCRX             := $220
+SCRY             := $224
+ADSCRL           := $218
+ADSCRH           := $21C
+
 
 ; ---------------------------------------------------------------------------
 ; Page $500
index 06e39b36ffdcb73a8612838b6dde52571ecb740f..9e4ecd8cea7bd2d294bf2dd65fb07f7d3e816955 100644 (file)
@@ -4,7 +4,7 @@ SYMBOLS {
 MEMORY {
     ZP:  file = "", define = yes, start = $0020, size = $00E0;
     RAM: file = "", define = yes, start = $01FA, size = $0206;
-    ROM: file = %O, define = yes, start = $B000, size = $1000;
+    ROM: file = %O, define = yes, start = $B000, size = $1000, fill = yes, fillval = $FF;
 }
 SEGMENTS {
     ZEROPAGE: load = ZP,             type = zp;
index 80dba89b8b492e1ca85675a1f67b0c91fcf803ca..6a08cc3c395d118da661c40e653853b5c6707262 100644 (file)
@@ -4,7 +4,7 @@
 <title>cc65 Users Guide
 <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
 <url url="mailto:gregdk@users.sf.net" name="Greg King">
-<date>2016-06-11
+<date>2017-02-27
 
 <abstract>
 cc65 is a C compiler for 6502 targets. It supports several 6502 based home
@@ -687,30 +687,37 @@ This cc65 version has some extensions to the ISO C standard.
        string.
        <p>
 
-<item>         cc65 allows the initialization of <tt/void/ variables. This may be
-       used to create variable structures that are more compatible with
-       interfaces written for assembler languages. Here is an example:
+<item>  cc65 allows the initialization of <tt/void/ variables. This may be
+        used to create arbitrary structures that are more compatible with
+        interfaces written for assembler languages. Here is an example:
 
-       <tscreen><verb>
-       void GCmd = {   (char)3, (unsigned)0x2000, (unsigned)0x3000 };
-       </verb></tscreen>
+        <tscreen><verb>
+        void GCmd = { (char)3, (unsigned)0x2000, (unsigned)0x3000 };
+        </verb></tscreen>
 
-       This will be translated as follows:
+        That will be translated as follows:
 
-       <tscreen><verb>
-       _GCmd:
-               .byte   3
-               .word   $2000
-               .word   $3000
-       </verb></tscreen>
+        <tscreen><verb>
+        _GCmd:
+                .byte   3
+                .word   $2000
+                .word   $3000
+        </verb></tscreen>
 
-       Since the variable is of type <tt/void/ you may not use it as is.
-       However, taking the address of the variable results in a <tt/void*/
-       which may be passed to any function expecting a pointer.
+        Since the variable is of type <tt/void/, you may not use it as-is.
+        However, taking the address of the variable results in a <tt/void*/
+        which may be passed to any function expecting a pointer.  Also, the
+        <tt/sizeof/ operator will give the length of the initializer:
 
-       See the <url url="geos.html" name="GEOS library document"> for examples
-       on how to use this feature.
-       <p>
+        <tscreen><verb>
+        GLen = sizeof GCmd;
+        </verb></tscreen>
+
+        will assign the value 5 to <tt/GLen/.
+
+        See the <url url="geos.html" name="GEOS library document"> for examples
+        on how to use that feature.
+        <p>
 
 <item>  cc65 implements flexible array struct members as defined in the C99 ISO
         standard. As an extension, these fields may be initialized. There are
index 9032156eeb5375f4fc32123819f4f2c9b367da82..fda4dee86731da4e2fd7812d05ee575b8af4d7aa 100644 (file)
@@ -141,7 +141,7 @@ Telestrat manages also mouse, but it had been no handled yet in this version.
 
 Telestrat has a RS232 port, but it's not used
 
-</descrip><
+</descrip>
 
 <sect>Limitations<label id="limitations"><p>
 
index 57fe0cd240ad343bd353f8baa5d14f11718c47c8..d6ab5fee179327c57b1a4dab5f9ed99a3863d05b 100644 (file)
@@ -1,47 +1,47 @@
-/*****************************************************************************/\r
-/*                                                                           */\r
-/*                                osic1p.h                                   */\r
-/*                                                                           */\r
-/*                Challenger 1P system specific definitions                  */\r
-/*                                                                           */\r
-/*                                                                           */\r
-/*                                                                           */\r
-/* (C) 2015 Stephan Muehlstrasser                                            */\r
-/*                                                                           */\r
-/*                                                                           */\r
-/* This software is provided 'as-is', without any expressed or implied       */\r
-/* warranty.  In no event will the authors be held liable for any damages    */\r
-/* arising from the use of this software.                                    */\r
-/*                                                                           */\r
-/* Permission is granted to anyone to use this software for any purpose,     */\r
-/* including commercial applications, and to alter it and redistribute it    */\r
-/* freely, subject to the following restrictions:                            */\r
-/*                                                                           */\r
-/* 1. The origin of this software must not be misrepresented; you must not   */\r
-/*    claim that you wrote the original software. If you use this software   */\r
-/*    in a product, an acknowledgment in the product documentation would be  */\r
-/*    appreciated but is not required.                                       */\r
-/* 2. Altered source versions must be plainly marked as such, and must not   */\r
-/*    be misrepresented as being the original software.                      */\r
-/* 3. This notice may not be removed or altered from any source              */\r
-/*    distribution.                                                          */\r
-/*                                                                           */\r
-/*****************************************************************************/\r
-\r
-#ifndef _OSIC1P_H\r
-#define _OSIC1P_H\r
-\r
-/* Check for errors */\r
-#if !defined(__OSIC1P__)\r
-#  error "This module may only be used when compiling for the Challenger 1P!"\r
-#endif\r
-\r
-/* The following #defines will cause the matching functions calls in conio.h\r
-** to be overlaid by macros with the same names, saving the function call\r
-** overhead.\r
-*/\r
-#define _textcolor(color)       COLOR_WHITE\r
-#define _bgcolor(color)         COLOR_BLACK\r
-#define _bordercolor(color)     COLOR_BLACK\r
-\r
-#endif\r
+/*****************************************************************************/
+/*                                                                           */
+/*                                osic1p.h                                   */
+/*                                                                           */
+/*                Challenger 1P system specific definitions                  */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2015 Stephan Muehlstrasser                                            */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef _OSIC1P_H
+#define _OSIC1P_H
+
+/* Check for errors */
+#if !defined(__OSIC1P__)
+#  error "This module may only be used when compiling for the Challenger 1P!"
+#endif
+
+/* The following #defines will cause the matching functions calls in conio.h
+** to be overlaid by macros with the same names, saving the function call
+** overhead.
+*/
+#define _textcolor(color)       COLOR_WHITE
+#define _bgcolor(color)         COLOR_BLACK
+#define _bordercolor(color)     COLOR_BLACK
+
+#endif
index 8fa6a2bd12c7c035e545e7a04f7e79e0a3fd6bbb..8ced898004a4cc7364a2c2d0f839a0e0e0971e5c 100644 (file)
-/*****************************************************************************/\r
-/*                                                                           */\r
-/*                                  zlib.h                                   */\r
-/*                                                                           */\r
-/*              Decompression routines for the 'deflate' format              */\r
-/*                                                                           */\r
-/*                                                                           */\r
-/*                                                                           */\r
-/* (C) 2000-2015 Piotr Fusik <fox@scene.pl>                                  */\r
-/*                                                                           */\r
-/* This file is based on the zlib.h from 'zlib' general purpose compression  */\r
-/* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler.    */\r
-/*                                                                           */\r
-/*  Jean-loup Gailly        Mark Adler                                       */\r
-/*  jloup@gzip.org          madler@alumni.caltech.edu                        */\r
-/*                                                                           */\r
-/* This software is provided 'as-is', without any expressed or implied       */\r
-/* warranty.  In no event will the authors be held liable for any damages    */\r
-/* arising from the use of this software.                                    */\r
-/*                                                                           */\r
-/* Permission is granted to anyone to use this software for any purpose,     */\r
-/* including commercial applications, and to alter it and redistribute it    */\r
-/* freely, subject to the following restrictions:                            */\r
-/*                                                                           */\r
-/* 1. The origin of this software must not be misrepresented; you must not   */\r
-/*    claim that you wrote the original software. If you use this software   */\r
-/*    in a product, an acknowledgment in the product documentation would be  */\r
-/*    appreciated but is not required.                                       */\r
-/* 2. Altered source versions must be plainly marked as such, and must not   */\r
-/*    be misrepresented as being the original software.                      */\r
-/* 3. This notice may not be removed or altered from any source              */\r
-/*    distribution.                                                          */\r
-/*                                                                           */\r
-/*****************************************************************************/\r
-\r
-\r
-\r
-#ifndef _ZLIB_H\r
-#define _ZLIB_H\r
-\r
-#define Z_OK         0\r
-#define Z_DATA_ERROR (-3)\r
-/* Return codes for uncompress() */\r
-\r
-#define Z_DEFLATED   8\r
-/* The deflate compression method (the only one supported) */\r
-\r
-#define Z_NULL       0\r
-\r
-\r
-unsigned __fastcall__ inflatemem (char* dest, const char* source);\r
-/*\r
-     Decompresses the source buffer into the destination buffer.\r
-   Returns the size of the uncompressed data (number of bytes written starting\r
-   from dest).\r
-\r
-     This function expects data in the DEFLATE format, described in RFC\r
-   (Request for Comments) 1951 in the file\r
-   ftp://ds.internic.net/rfc/rfc1951.txt.\r
-\r
-     This function does not exist in the original zlib. Its implementation\r
-   using original zlib might be following:\r
-\r
-   unsigned inflatemem (char* dest, const char* source)\r
-   {\r
-     z_stream stream;\r
-\r
-     stream.next_in = (Bytef*) source;\r
-     stream.avail_in = 65535;\r
-\r
-     stream.next_out = dest;\r
-     stream.avail_out = 65535;\r
-\r
-     stream.zalloc = (alloc_func) 0;\r
-     stream.zfree = (free_func) 0;\r
-\r
-     inflateInit2(&stream, -MAX_WBITS);\r
-     inflate(&stream, Z_FINISH);\r
-     inflateEnd(&stream);\r
-\r
-     return stream.total_out;\r
-   }\r
-*/\r
-\r
-\r
-int __fastcall__ uncompress (char* dest, unsigned* destLen,\r
-                             const char* source, unsigned sourceLen);\r
-/*\r
-   Original zlib description:\r
-\r
-     Decompresses the source buffer into the destination buffer.  sourceLen is\r
-   the byte length of the source buffer. Upon entry, destLen is the total\r
-   size of the destination buffer, which must be large enough to hold the\r
-   entire uncompressed data. (The size of the uncompressed data must have\r
-   been saved previously by the compressor and transmitted to the decompressor\r
-   by some mechanism outside the scope of this compression library.)\r
-   Upon exit, destLen is the actual size of the compressed buffer.\r
-     This function can be used to decompress a whole file at once if the\r
-   input file is mmap'ed.\r
-\r
-     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not\r
-   enough memory, Z_BUF_ERROR if there was not enough room in the output\r
-   buffer, or Z_DATA_ERROR if the input data was corrupted.\r
-\r
-   Implementation notes:\r
-\r
-     This function expects data in the ZLIB format, described in RFC 1950\r
-   in the file ftp://ds.internic.net/rfc/rfc1950.txt. The ZLIB format is\r
-   essentially the DEFLATE format plus a very small header and Adler-32\r
-   checksum.\r
-\r
-     Z_MEM_ERROR and Z_BUF_ERROR are never returned in this implementation.\r
-*/\r
-\r
-\r
-unsigned long __fastcall__ adler32 (unsigned long adler, const char* buf,\r
-                                    unsigned len);\r
-\r
-/*\r
-   Original zlib description:\r
-\r
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and\r
-   return the updated checksum. If buf is NULL, this function returns\r
-   the required initial value for the checksum.\r
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed\r
-   much faster. Usage example:\r
-\r
-     unsigned long adler = adler32(0L, Z_NULL, 0);\r
-\r
-     while (read_buffer(buffer, length) != EOF) {\r
-       adler = adler32(adler, buffer, length);\r
-     }\r
-     if (adler != original_adler) error();\r
-\r
-   Implementation notes:\r
-\r
-     This function isn't actually much faster than crc32(), but it is smaller\r
-   and does not use any lookup tables.\r
-*/\r
-\r
-\r
-unsigned long __fastcall__ crc32 (unsigned long crc, const char* buf,\r
-                                  unsigned len);\r
-/*\r
-   Original zlib description:\r
-\r
-     Update a running crc with the bytes buf[0..len-1] and return the updated\r
-   crc. If buf is NULL, this function returns the required initial value\r
-   for the crc. Pre- and post-conditioning (one's complement) is performed\r
-   within this function so it shouldn't be done by the application.\r
-   Usage example:\r
-\r
-     unsigned long crc = crc32(0L, Z_NULL, 0);\r
-\r
-     while (read_buffer(buffer, length) != EOF) {\r
-       crc = crc32(crc, buffer, length);\r
-     }\r
-     if (crc != original_crc) error();\r
-\r
-   Implementation notes:\r
-\r
-     This function uses statically allocated 1 KB lookup table. The table is\r
-   initialised before it is used for the first time (that is, if buffer is\r
-   NULL or length is zero, then the lookup table isn't initialised).\r
-*/\r
-\r
-\r
-/* end of zlib.h */\r
-#endif\r
-\r
-\r
-\r
+/*****************************************************************************/
+/*                                                                           */
+/*                                  zlib.h                                   */
+/*                                                                           */
+/*              Decompression routines for the 'deflate' format              */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2000-2015 Piotr Fusik <fox@scene.pl>                                  */
+/*                                                                           */
+/* This file is based on the zlib.h from 'zlib' general purpose compression  */
+/* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler.    */
+/*                                                                           */
+/*  Jean-loup Gailly        Mark Adler                                       */
+/*  jloup@gzip.org          madler@alumni.caltech.edu                        */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#define Z_OK         0
+#define Z_DATA_ERROR (-3)
+/* Return codes for uncompress() */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported) */
+
+#define Z_NULL       0
+
+
+unsigned __fastcall__ inflatemem (char* dest, const char* source);
+/*
+     Decompresses the source buffer into the destination buffer.
+   Returns the size of the uncompressed data (number of bytes written starting
+   from dest).
+
+     This function expects data in the DEFLATE format, described in RFC
+   (Request for Comments) 1951 in the file
+   ftp://ds.internic.net/rfc/rfc1951.txt.
+
+     This function does not exist in the original zlib. Its implementation
+   using original zlib might be following:
+
+   unsigned inflatemem (char* dest, const char* source)
+   {
+     z_stream stream;
+
+     stream.next_in = (Bytef*) source;
+     stream.avail_in = 65535;
+
+     stream.next_out = dest;
+     stream.avail_out = 65535;
+
+     stream.zalloc = (alloc_func) 0;
+     stream.zfree = (free_func) 0;
+
+     inflateInit2(&stream, -MAX_WBITS);
+     inflate(&stream, Z_FINISH);
+     inflateEnd(&stream);
+
+     return stream.total_out;
+   }
+*/
+
+
+int __fastcall__ uncompress (char* dest, unsigned* destLen,
+                             const char* source, unsigned sourceLen);
+/*
+   Original zlib description:
+
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+
+   Implementation notes:
+
+     This function expects data in the ZLIB format, described in RFC 1950
+   in the file ftp://ds.internic.net/rfc/rfc1950.txt. The ZLIB format is
+   essentially the DEFLATE format plus a very small header and Adler-32
+   checksum.
+
+     Z_MEM_ERROR and Z_BUF_ERROR are never returned in this implementation.
+*/
+
+
+unsigned long __fastcall__ adler32 (unsigned long adler, const char* buf,
+                                    unsigned len);
+
+/*
+   Original zlib description:
+
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     unsigned long adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+
+   Implementation notes:
+
+     This function isn't actually much faster than crc32(), but it is smaller
+   and does not use any lookup tables.
+*/
+
+
+unsigned long __fastcall__ crc32 (unsigned long crc, const char* buf,
+                                  unsigned len);
+/*
+   Original zlib description:
+
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+
+     unsigned long crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+
+   Implementation notes:
+
+     This function uses statically allocated 1 KB lookup table. The table is
+   initialised before it is used for the first time (that is, if buffer is
+   NULL or length is zero, then the lookup table isn't initialised).
+*/
+
+
+/* end of zlib.h */
+#endif
+
+
+
index 54b54860c3ab9987bf35f0942be15c4d0b14946d..f4aa031014f54e6bf6e402e897d94435960a746b 100644 (file)
@@ -1,4 +1,3 @@
-
 ifneq ($(shell echo),)
   CMD_EXE = 1
 endif
@@ -15,24 +14,24 @@ CBMS = c128   \
 GEOS = geos-apple \
        geos-cbm
 
-TARGETS = apple2    \
-          apple2enh \
-          atari     \
-          atarixl   \
-          atari2600 \
-          atari5200 \
-          atmos     \
+TARGETS = apple2       \
+          apple2enh    \
+          atari        \
+          atarixl      \
+          atari2600    \
+          atari5200    \
+          atmos        \
           creativision \
-          $(CBMS)   \
-          $(GEOS)   \
-          gamate    \
-          lynx      \
-          nes       \
-          osic1p    \
-          pce       \
-          sim6502   \
-          sim65c02  \
-          supervision\
+          $(CBMS)      \
+          $(GEOS)      \
+          gamate       \
+          lynx         \
+          nes          \
+          osic1p       \
+          pce          \
+          sim6502      \
+          sim65c02     \
+          supervision  \
           telestrat
 
 DRVTYPES = emd \
@@ -41,13 +40,13 @@ DRVTYPES = emd \
            ser \
            tgi
 
-OUTPUTDIRS := lib                 \
-              asminc              \
-              cfg                 \
-              include             \
-              $(subst ../,,$(filter-out $(wildcard ../include/*.*),$(wildcard ../include/*)))\
-              $(subst ../,,$(wildcard ../target/*/drv/*))\
-              $(subst ../,,$(wildcard ../target/*/util))\
+OUTPUTDIRS := lib                                                                             \
+              asminc                                                                          \
+              cfg                                                                             \
+              include                                                                         \
+              $(subst ../,,$(filter-out $(wildcard ../include/*.*),$(wildcard ../include/*))) \
+              $(subst ../,,$(wildcard ../target/*/drv/*))                                     \
+              $(subst ../,,$(wildcard ../target/*/util))
 
 .PHONY: all mostlyclean clean install zip lib $(TARGETS)
 
index bf44a0ecc522c251e45cf5130cdd45792effed04..39f323d28f3c4ee9f69ab66e0a9545a8d6e6e9f6 100644 (file)
-;\r
-; Extended memory driver for 65816 based extra RAM. Driver works without\r
-; problems when statically linked.\r
-;\r
-; Marco van den Heuvel, 2015-12-01\r
-;\r
-\r
-        .include        "zeropage.inc"\r
-\r
-        .include        "em-kernel.inc"\r
-        .include        "em-error.inc"\r
-\r
-\r
-        .macpack        generic\r
-        .macpack        module\r
-\r
-\r
-; ------------------------------------------------------------------------\r
-; Header. Includes jump table\r
-\r
-        module_header   _c64_65816_emd\r
-\r
-; Driver signature\r
-\r
-        .byte   $65, $6d, $64           ; "emd"\r
-        .byte   EMD_API_VERSION         ; EM API version number\r
-\r
-; Library reference\r
-\r
-        .addr   $0000\r
-\r
-; Jump table\r
-\r
-        .addr   INSTALL\r
-        .addr   UNINSTALL\r
-        .addr   PAGECOUNT\r
-        .addr   MAP\r
-        .addr   USE\r
-        .addr   COMMIT\r
-        .addr   COPYFROM\r
-        .addr   COPYTO\r
-\r
-; ------------------------------------------------------------------------\r
-; Data.\r
-\r
-.bss\r
-isnotscpu:      .res    1               ; SuperCPU not present\r
-curpage:        .res    1               ; Current page number\r
-curbank:        .res    1               ; Current bank number (+1)\r
-bankcount:      .res    1               ; Number of available banks (pages = banks * 256)\r
-window:         .res    256             ; Memory "window"\r
-\r
-.code\r
-\r
-; ------------------------------------------------------------------------\r
-; INSTALL routine. Is called after the driver is loaded into memory. If\r
-; possible, check if the hardware is present and determine the amount of\r
-; memory available.\r
-; Must return an EM_ERR_xx code in a/x.\r
-;\r
-\r
-INSTALL:\r
-        sei\r
-        clc\r
-        sed\r
-        lda     #$99\r
-        adc     #$01                    ; on 65C02, 65SC02, 65CE02, 65802 and 65816 sets the zero flag correctly\r
-        cld\r
-        bne     @not_present\r
-        clc\r
-.P816\r
-        sep     #$01                    ; nop #$01 on 65C02/65SC02 and lda ($01,s),y on 65CE02\r
-.P02\r
-        bcc     @not_present\r
-        lda     $d0bc\r
-        and     #$80\r
-        sta     isnotscpu\r
-        lda     $07e8\r
-        pha                             ; save value incase it was used somewhere else\r
-        ldx     #$ff\r
-@fillloop:                              ; fill from top (bank 255) to bottom\r
-        txa\r
-        pha\r
-.P816\r
-        plb                             ; pull dbr\r
-.P02\r
-        stx     $07e8\r
-        dex\r
-        cpx     #$ff\r
-        bne     @fillloop\r
-        inx\r
-@compareloop:                           ; check from bottom to top\r
-        txa\r
-        pha\r
-.P816\r
-        plb\r
-.P02\r
-        cmp     $07e8\r
-        bne     @found_pages\r
-.P816\r
-        inc\r
-.P02\r
-        sta     $07e8\r
-        cmp     $07e8\r
-        bne     @found_pages\r
-        inx\r
-        bne     @compareloop\r
-@found_pages:\r
-        dex\r
-        lda     #$00\r
-        pha\r
-.P816\r
-        plb\r
-.P02\r
-        pla\r
-        sta     $07e8\r
-        cli\r
-        lda     isnotscpu\r
-        bne     @noextradex\r
-        dex\r
-@noextradex:\r
-        stx     bankcount\r
-        lda     #<EM_ERR_OK\r
-        ldx     #>EM_ERR_OK\r
-        rts\r
-@not_present:\r
-        cli\r
-        lda     #<EM_ERR_NO_DEVICE\r
-        ldx     #>EM_ERR_NO_DEVICE\r
-;       rts                             ; Run into UNINSTALL instead\r
-\r
-\r
-; ------------------------------------------------------------------------\r
-; UNINSTALL routine. Is called before the driver is removed from memory.\r
-; Can do cleanup or whatever. Must not return anything.\r
-;\r
-\r
-UNINSTALL:\r
-        rts\r
-\r
-\r
-; ------------------------------------------------------------------------\r
-; PAGECOUNT: Return the total number of available pages in a/x.\r
-;\r
-\r
-PAGECOUNT:\r
-        lda     #$00                   ; a whole bank is either usable or not\r
-        ldx     bankcount\r
-        rts\r
-\r
-; ------------------------------------------------------------------------\r
-; MAP: Map the page in a/x into memory and return a pointer to the page in\r
-; a/x. The contents of the currently mapped page (if any) may be discarded\r
-; by the driver.\r
-;\r
-\r
-MAP:    sta     curpage                 ; Remember the new page\r
-        stx     curbank                 ; Remember the new bank\r
-\r
-        sta     ptr2+1                  ; src address low\r
-        lda     #$00\r
-        sta     ptr2                    ; src address high\r
-        inx\r
-        ldy     isnotscpu               ; check if not scpu\r
-        bne     @notscpu\r
-        inx\r
-@notscpu:\r
-        stx     tmp2                    ; src bank\r
-\r
-        sta     tmp1                    ; dst bank\r
-\r
-        sta     ptr3+1                  ; length high\r
-        lda     #$ff\r
-        sta     ptr3                    ; length low\r
-\r
-        lda     #<window\r
-        sta     ptr1                    ; dst address low\r
-        ldx     #>window\r
-        stx     ptr1+1                  ; dst address high\r
-\r
-        jsr     transfer\r
-\r
-        rts\r
-\r
-; ------------------------------------------------------------------------\r
-; USE: Tell the driver that the window is now associated with a given page.\r
-\r
-USE:    sta     curpage                 ; Remember the page\r
-        stx     curbank                 ; Remember the bank\r
-        lda     #<window\r
-        ldx     #>window                ; Return the window\r
-        rts\r
-\r
-; ------------------------------------------------------------------------\r
-; COMMIT: Commit changes in the memory window to extended storage.\r
-\r
-COMMIT: lda     curpage                 ; Get the current page\r
-        sta     ptr1+1                  ; dst high\r
-        ldx     #$00\r
-        stx     ptr1                    ; dst low\r
-\r
-        lda     #<window\r
-        sta     ptr2                    ; src low\r
-        lda     #>window\r
-        sta     ptr2+1                  ; src high\r
-\r
-        stx     ptr3+1                  ; length high\r
-        lda     #$ff\r
-        sta     ptr3                    ; length low\r
-\r
-        stx     tmp2                    ; src bank\r
-        ldy     curbank                 ; Get the current bank\r
-        iny\r
-        ldx     isnotscpu\r
-        bne     @notascpu\r
-        iny\r
-@notascpu:\r
-        sty     tmp1                    ; dst bank\r
-\r
-        jsr     transfer\r
-\r
-        rts\r
-\r
-; ------------------------------------------------------------------------\r
-; COPYFROM: Copy from extended into linear memory. A pointer to a structure\r
-; describing the request is passed in a/x.\r
-; The function must not return anything.\r
-;\r
-\r
-COPYFROM:\r
-        sta     ptr4\r
-        stx     ptr4+1                  ; Save the passed em_copy pointer\r
-\r
-        ldy     #EM_COPY::COUNT+1       ; start at the end of the struct\r
-        lda     (ptr4),y                ; get high byte of count\r
-        tax\r
-        dey\r
-        lda     (ptr4),y                ; get low byte of count\r
-        bne     @nodex\r
-        dex\r
-@nodex:\r
-.P816\r
-        dec\r
-.P02\r
-        sta     ptr3                    ; length low\r
-        stx     ptr3+1                  ; length high\r
-        dey\r
-        lda     (ptr4),y                ; get bank\r
-.P816\r
-        inc\r
-.P02\r
-        ldx     isnotscpu\r
-        bne     @notscpu64\r
-.P816\r
-        inc\r
-.P02\r
-@notscpu64:\r
-        sta     tmp2                    ; src bank\r
-        dey\r
-        lda     (ptr4),y                ; get page\r
-        sta     ptr2+1                  ; src high\r
-        dey\r
-        lda     (ptr4),y                ; get offset in page\r
-        sta     ptr2                    ; src low\r
-        dey\r
-        lda     (ptr4),y                ; get memory buffer high\r
-        sta     ptr1+1                  ; dst high\r
-        dey\r
-        lda     (ptr4),y                ; get memory buffer low\r
-        sta     ptr1                    ; dst low\r
-        lda     #$00\r
-        sta     tmp1                    ; dst bank\r
-\r
-        jsr     transfer\r
-\r
-        rts\r
-\r
-; ------------------------------------------------------------------------\r
-; COPYTO: Copy from linear into extended memory. A pointer to a structure\r
-; describing the request is passed in a/x.\r
-; The function must not return anything.\r
-;\r
-\r
-COPYTO: sta     ptr4\r
-        stx     ptr4+1                  ; Save the passed em_copy pointer\r
-\r
-        ldy     #EM_COPY::COUNT+1       ; start at the end of the struct\r
-        lda     (ptr4),y                ; get high byte of count\r
-        tax\r
-        dey\r
-        lda     (ptr4),y                ; get low byte of count\r
-        bne     @nodex2\r
-        dex\r
-@nodex2:\r
-.P816\r
-        dec\r
-.P02\r
-        sta     ptr3                    ; length low\r
-        txa\r
-        sta     ptr3+1                  ; length high\r
-        dey\r
-        lda     (ptr4),y                ; get bank\r
-.P816\r
-        inc\r
-.P02\r
-        ldx     isnotscpu\r
-        bne     @notascpu64\r
-.P816\r
-        inc\r
-.P02\r
-@notascpu64:\r
-        sta     tmp1                    ; dst bank\r
-        dey\r
-        lda     (ptr4),y                ; get page\r
-        sta     ptr1+1                  ; dst high\r
-        dey\r
-        lda     (ptr4),y                ; get page offset\r
-        sta     ptr1                    ; dst low\r
-        dey\r
-        lda     (ptr4),y                ; get memory buffer high\r
-        sta     ptr2+1                  ; src low\r
-        dey\r
-        lda     (ptr4),y                ; get memory buffer low\r
-        sta     ptr2                    ; src high\r
-        lda     #$00\r
-        sta     tmp2                    ; src bank\r
-\r
-        jsr     transfer\r
-\r
-        rts\r
-\r
-; ------------------------------------------------------------------------\r
-; Helper function for moving a block, the following is used:\r
-; ptr1: dst\r
-; ptr2: src\r
-; ptr3: length\r
-; tmp1: dst bank\r
-; tmp2: src bank\r
-\r
-transfer:\r
-.P816\r
-.A8\r
-.I8\r
-        sei\r
-        pha\r
-        phx\r
-        phy\r
-        ldx     tmp1                    ; load srcbank\r
-        stx     @move+1                 ; store srcbank in move + 1\r
-        ldy     tmp2                    ; load dstbank\r
-        sty     @move+2                 ; store dstbank in move + 2\r
-        clc                             ; switch to native mode\r
-        xce\r
-        php                             ; save status bits\r
-        rep     #%00110000              ; set A and index to 16bit\r
-.A16\r
-.I16\r
-        ldy     ptr1\r
-        ldx     ptr2\r
-        lda     ptr3\r
-@move:\r
-        mvn 0,0\r
-        plp                             ; restore status bits\r
-.A8\r
-.I8\r
-        lda     #$00\r
-        pha\r
-        plb                             ; restore dbr\r
-        sec\r
-        xce                             ; switch to emul mode\r
-        ply\r
-        plx\r
-        pla\r
-        cli\r
-        rts\r
-.P02\r
+;
+; Extended memory driver for 65816 based extra RAM. Driver works without
+; problems when statically linked.
+;
+; Marco van den Heuvel, 2015-12-01
+;
+
+        .include        "zeropage.inc"
+
+        .include        "em-kernel.inc"
+        .include        "em-error.inc"
+
+
+        .macpack        generic
+        .macpack        module
+
+
+; ------------------------------------------------------------------------
+; Header. Includes jump table
+
+        module_header   _c64_65816_emd
+
+; Driver signature
+
+        .byte   $65, $6d, $64           ; "emd"
+        .byte   EMD_API_VERSION         ; EM API version number
+
+; Library reference
+
+        .addr   $0000
+
+; Jump table
+
+        .addr   INSTALL
+        .addr   UNINSTALL
+        .addr   PAGECOUNT
+        .addr   MAP
+        .addr   USE
+        .addr   COMMIT
+        .addr   COPYFROM
+        .addr   COPYTO
+
+; ------------------------------------------------------------------------
+; Data.
+
+.bss
+isnotscpu:      .res    1               ; SuperCPU not present
+curpage:        .res    1               ; Current page number
+curbank:        .res    1               ; Current bank number (+1)
+bankcount:      .res    1               ; Number of available banks (pages = banks * 256)
+window:         .res    256             ; Memory "window"
+
+.code
+
+; ------------------------------------------------------------------------
+; INSTALL routine. Is called after the driver is loaded into memory. If
+; possible, check if the hardware is present and determine the amount of
+; memory available.
+; Must return an EM_ERR_xx code in a/x.
+;
+
+INSTALL:
+        sei
+        clc
+        sed
+        lda     #$99
+        adc     #$01                    ; on 65C02, 65SC02, 65CE02, 65802 and 65816 sets the zero flag correctly
+        cld
+        bne     @not_present
+        clc
+.P816
+        sep     #$01                    ; nop #$01 on 65C02/65SC02 and lda ($01,s),y on 65CE02
+.P02
+        bcc     @not_present
+        lda     $d0bc
+        and     #$80
+        sta     isnotscpu
+        lda     $07e8
+        pha                             ; save value incase it was used somewhere else
+        ldx     #$ff
+@fillloop:                              ; fill from top (bank 255) to bottom
+        txa
+        pha
+.P816
+        plb                             ; pull dbr
+.P02
+        stx     $07e8
+        dex
+        cpx     #$ff
+        bne     @fillloop
+        inx
+@compareloop:                           ; check from bottom to top
+        txa
+        pha
+.P816
+        plb
+.P02
+        cmp     $07e8
+        bne     @found_pages
+.P816
+        inc
+.P02
+        sta     $07e8
+        cmp     $07e8
+        bne     @found_pages
+        inx
+        bne     @compareloop
+@found_pages:
+        dex
+        lda     #$00
+        pha
+.P816
+        plb
+.P02
+        pla
+        sta     $07e8
+        cli
+        lda     isnotscpu
+        bne     @noextradex
+        dex
+@noextradex:
+        stx     bankcount
+        lda     #<EM_ERR_OK
+        ldx     #>EM_ERR_OK
+        rts
+@not_present:
+        cli
+        lda     #<EM_ERR_NO_DEVICE
+        ldx     #>EM_ERR_NO_DEVICE
+;       rts                             ; Run into UNINSTALL instead
+
+
+; ------------------------------------------------------------------------
+; UNINSTALL routine. Is called before the driver is removed from memory.
+; Can do cleanup or whatever. Must not return anything.
+;
+
+UNINSTALL:
+        rts
+
+
+; ------------------------------------------------------------------------
+; PAGECOUNT: Return the total number of available pages in a/x.
+;
+
+PAGECOUNT:
+        lda     #$00                   ; a whole bank is either usable or not
+        ldx     bankcount
+        rts
+
+; ------------------------------------------------------------------------
+; MAP: Map the page in a/x into memory and return a pointer to the page in
+; a/x. The contents of the currently mapped page (if any) may be discarded
+; by the driver.
+;
+
+MAP:    sta     curpage                 ; Remember the new page
+        stx     curbank                 ; Remember the new bank
+
+        sta     ptr2+1                  ; src address low
+        lda     #$00
+        sta     ptr2                    ; src address high
+        inx
+        ldy     isnotscpu               ; check if not scpu
+        bne     @notscpu
+        inx
+@notscpu:
+        stx     tmp2                    ; src bank
+
+        sta     tmp1                    ; dst bank
+
+        sta     ptr3+1                  ; length high
+        lda     #$ff
+        sta     ptr3                    ; length low
+
+        lda     #<window
+        sta     ptr1                    ; dst address low
+        ldx     #>window
+        stx     ptr1+1                  ; dst address high
+
+        jsr     transfer
+
+        rts
+
+; ------------------------------------------------------------------------
+; USE: Tell the driver that the window is now associated with a given page.
+
+USE:    sta     curpage                 ; Remember the page
+        stx     curbank                 ; Remember the bank
+        lda     #<window
+        ldx     #>window                ; Return the window
+        rts
+
+; ------------------------------------------------------------------------
+; COMMIT: Commit changes in the memory window to extended storage.
+
+COMMIT: lda     curpage                 ; Get the current page
+        sta     ptr1+1                  ; dst high
+        ldx     #$00
+        stx     ptr1                    ; dst low
+
+        lda     #<window
+        sta     ptr2                    ; src low
+        lda     #>window
+        sta     ptr2+1                  ; src high
+
+        stx     ptr3+1                  ; length high
+        lda     #$ff
+        sta     ptr3                    ; length low
+
+        stx     tmp2                    ; src bank
+        ldy     curbank                 ; Get the current bank
+        iny
+        ldx     isnotscpu
+        bne     @notascpu
+        iny
+@notascpu:
+        sty     tmp1                    ; dst bank
+
+        jsr     transfer
+
+        rts
+
+; ------------------------------------------------------------------------
+; COPYFROM: Copy from extended into linear memory. A pointer to a structure
+; describing the request is passed in a/x.
+; The function must not return anything.
+;
+
+COPYFROM:
+        sta     ptr4
+        stx     ptr4+1                  ; Save the passed em_copy pointer
+
+        ldy     #EM_COPY::COUNT+1       ; start at the end of the struct
+        lda     (ptr4),y                ; get high byte of count
+        tax
+        dey
+        lda     (ptr4),y                ; get low byte of count
+        bne     @nodex
+        dex
+@nodex:
+.P816
+        dec
+.P02
+        sta     ptr3                    ; length low
+        stx     ptr3+1                  ; length high
+        dey
+        lda     (ptr4),y                ; get bank
+.P816
+        inc
+.P02
+        ldx     isnotscpu
+        bne     @notscpu64
+.P816
+        inc
+.P02
+@notscpu64:
+        sta     tmp2                    ; src bank
+        dey
+        lda     (ptr4),y                ; get page
+        sta     ptr2+1                  ; src high
+        dey
+        lda     (ptr4),y                ; get offset in page
+        sta     ptr2                    ; src low
+        dey
+        lda     (ptr4),y                ; get memory buffer high
+        sta     ptr1+1                  ; dst high
+        dey
+        lda     (ptr4),y                ; get memory buffer low
+        sta     ptr1                    ; dst low
+        lda     #$00
+        sta     tmp1                    ; dst bank
+
+        jsr     transfer
+
+        rts
+
+; ------------------------------------------------------------------------
+; COPYTO: Copy from linear into extended memory. A pointer to a structure
+; describing the request is passed in a/x.
+; The function must not return anything.
+;
+
+COPYTO: sta     ptr4
+        stx     ptr4+1                  ; Save the passed em_copy pointer
+
+        ldy     #EM_COPY::COUNT+1       ; start at the end of the struct
+        lda     (ptr4),y                ; get high byte of count
+        tax
+        dey
+        lda     (ptr4),y                ; get low byte of count
+        bne     @nodex2
+        dex
+@nodex2:
+.P816
+        dec
+.P02
+        sta     ptr3                    ; length low
+        txa
+        sta     ptr3+1                  ; length high
+        dey
+        lda     (ptr4),y                ; get bank
+.P816
+        inc
+.P02
+        ldx     isnotscpu
+        bne     @notascpu64
+.P816
+        inc
+.P02
+@notascpu64:
+        sta     tmp1                    ; dst bank
+        dey
+        lda     (ptr4),y                ; get page
+        sta     ptr1+1                  ; dst high
+        dey
+        lda     (ptr4),y                ; get page offset
+        sta     ptr1                    ; dst low
+        dey
+        lda     (ptr4),y                ; get memory buffer high
+        sta     ptr2+1                  ; src low
+        dey
+        lda     (ptr4),y                ; get memory buffer low
+        sta     ptr2                    ; src high
+        lda     #$00
+        sta     tmp2                    ; src bank
+
+        jsr     transfer
+
+        rts
+
+; ------------------------------------------------------------------------
+; Helper function for moving a block, the following is used:
+; ptr1: dst
+; ptr2: src
+; ptr3: length
+; tmp1: dst bank
+; tmp2: src bank
+
+transfer:
+.P816
+.A8
+.I8
+        sei
+        pha
+        phx
+        phy
+        ldx     tmp1                    ; load srcbank
+        stx     @move+1                 ; store srcbank in move + 1
+        ldy     tmp2                    ; load dstbank
+        sty     @move+2                 ; store dstbank in move + 2
+        clc                             ; switch to native mode
+        xce
+        php                             ; save status bits
+        rep     #%00110000              ; set A and index to 16bit
+.A16
+.I16
+        ldy     ptr1
+        ldx     ptr2
+        lda     ptr3
+@move:
+        mvn 0,0
+        plp                             ; restore status bits
+.A8
+.I8
+        lda     #$00
+        pha
+        plb                             ; restore dbr
+        sec
+        xce                             ; switch to emul mode
+        ply
+        plx
+        pla
+        cli
+        rts
+.P02
index 9e723834546c4eb2522f8cdf3733be2e2c2f65b4..3c4856446e54d6b14531816ae8e914e4508f9453 100644 (file)
@@ -18,7 +18,7 @@ _clrscr:
         lda     #$50    ; VRAM offset high ($10 OR $40)
         sta     VDP_CONTROL_W
 
-        lda     #$C0    ; Space from ROM setup
+        lda     #$40    ; Space char from ROM setup
 
         ldx     #0
         ldy     #3
@@ -34,8 +34,8 @@ L1:     sta     VDP_DATA_W
         lda     #0
         sta     CURSOR_X
         sta     CURSOR_Y
-        sta     <SCREEN_PTR
+        sta     SCREEN_PTR
         lda     #$10
-        sta      >SCREEN_PTR
+        sta     SCREEN_PTR+1
 
         rts
index ff60494b9e2d1dc07c4e59a58cd253fc0d509911..437b738b2a3d62ea32fe2e616c8620ed9777ee88 100644 (file)
@@ -96,8 +96,8 @@ BAD_CHAR:
         jmp     plot
 
 ;-----------------------------------------------------------------------------
-; Initialize the conio subsystem. Code goes into the INIT segment, which may
-; be reused after startup.
+; Initialize the conio subsystem. "INIT" segment is nothing special on the
+; Creativision, it is part of the "ROM" memory.
 
 .segment        "INIT"
 
@@ -122,4 +122,4 @@ LL:     lda     boxchars,x
         bne     LL
 
         cli
-        jmp plot
+        jmp     plot
index 6faec38ebf0eee3db4caea7de347822cf363ee48..5185ff237fe979f2dc79e1a8ba060b066fc0fd91 100644 (file)
@@ -31,9 +31,6 @@ entry:
         ldx     #<__RAM_START__ - 1
         txs
 
-        ; Start interrupts
-        cli
-
         ; Clear the BSS data
         jsr     zerobss
 
@@ -49,13 +46,21 @@ entry:
         ; Call module constructors
         jsr     initlib
 
+        ; enable vertical blank interrupts in the display controller
+        lda      #$E0           ; 16K RAM, Active Display, Mode 1, VBI enabled
+        ldx      #$01           ; Register 1
+        jsr      BIOS_WRITE_VDP_REG
+
+        ; Start interrupts
+        cli
+
         ; Call main()
         jsr     callmain
 
         ; Call module destructors. This is also the _exit entry.
 _exit:  jsr     donelib
 
-        ; TODO: Replace with some sort of reset
+        ; A Creativision program isn't supposed to exit.
 loop:   jmp loop
 
 ; ------------------------------------------------------------------------
@@ -81,7 +86,7 @@ irq2:   jmp     BIOS_IRQ2_ADDR
         ; VDP Setup
         ; This sets to Graphics Mode 1
         .byte   $00             ; Register 0
-        .byte   $C0             ; Register 1 16K RAM, Active Display, Mode 1
+        .byte   $C0             ; Register 1 16K RAM, Active Display, Mode 1, VBI disabled
         .byte   $04             ; Register 2 Name Table at $1000 - $12FF
         .byte   $60             ; Register 3 Colour Table at $1800 - $181F
         .byte   $00             ; Register 4 Pattern Table at $0000 - $07FF
index 37b927d08c6fa40497e66cf15c963ca619f830ba..3f167464a1bdc1d3db5d250281b21cc1ff4f4a27 100644 (file)
@@ -1,60 +1,69 @@
 ;
 ; Standard joystick driver for the Creativision.
 ;
-; Christian Groessler, 2017-02-06
+; Christian Groessler, 2017-03-08
 ;
 
-        .include        "zeropage.inc"
+                .include        "zeropage.inc"
 
-        .include        "joy-kernel.inc"
-        .include        "joy-error.inc"
-        .include        "creativision.inc"
+                .include        "joy-kernel.inc"
+                .include        "joy-error.inc"
+                .include        "creativision.inc"
 
-        .macpack        module
+                .macpack        module
 
 
 ; ------------------------------------------------------------------------
 ; Header. Includes jump table
 
-        module_header   _creativisionstd_joy
+               module_header   _creativisionstd_joy
 
 ; Driver signature
 
-        .byte   $6A, $6F, $79           ; "joy"
-        .byte   JOY_API_VERSION         ; Driver API version number
+                .byte   $6A, $6F, $79           ; "joy"
+                .byte   JOY_API_VERSION         ; Driver API version number
 
 ; Library reference
 
-        .addr   $0000
+                .addr   $0000
 
-; Button state masks (8 values)
+; Symbolic names for joystick masks (similar names like the defines in joystick.h, but not related to them)
 
-        .byte   $10                     ; JOY_UP
-        .byte   $04                     ; JOY_DOWN
-        .byte   $20                     ; JOY_LEFT
-        .byte   $08                     ; JOY_RIGHT
-        .byte   $01                     ; JOY_FIRE (button #1)
-        .byte   $02                     ; JOY_FIRE2 (button #2)
-        .byte   $00                     ; Future expansion
-        .byte   $00                     ; Future expansion
+JOY_UP          =       $10
+JOY_DOWN        =       $04
+JOY_LEFT        =       $20
+JOY_RIGHT       =       $08
+JOY_FIRE        =       $01
+JOY_FIRE2       =       $02
+
+; Joystick state masks (8 values)
+
+                .byte   JOY_UP
+                .byte   JOY_DOWN
+                .byte   JOY_LEFT
+                .byte   JOY_RIGHT
+                .byte   JOY_FIRE
+                .byte   JOY_FIRE2
+                .byte   $00                     ; Future expansion
+                .byte   $00                     ; Future expansion
 
 ; Jump table.
 
-        .addr   INSTALL
-        .addr   UNINSTALL
-        .addr   COUNT
-        .addr   READJOY
-        .addr   0                       ; IRQ entry not used
+                .addr   INSTALL
+                .addr   UNINSTALL
+                .addr   COUNT
+                .addr   READJOY
+                .addr   0                       ; IRQ entry not used
 
 ; ------------------------------------------------------------------------
 ; Constants
 
-JOY_COUNT       = 2                     ; Number of joysticks we support
+JOY_COUNT       =       2                       ; Number of joysticks we support
 
 ; ------------------------------------------------------------------------
 ; Code
 
-        .code
+                .code
 
 ; ------------------------------------------------------------------------
 ; INSTALL routine. Is called after the driver is loaded into memory. If
@@ -63,131 +72,180 @@ JOY_COUNT       = 2                     ; Number of joysticks we support
 ; Must return an JOY_ERR_xx code in a/x.
 ;
 
-INSTALL:
-        lda     #JOY_ERR_OK
-        ldx     #0
-;       rts                             ; Fall through
+INSTALL:        lda     #JOY_ERR_OK
+                ldx     #0
+;               rts                             ; Fall through
 
 ; ------------------------------------------------------------------------
 ; UNINSTALL routine. Is called before the driver is removed from memory.
 ; Can do cleanup or whatever. Must not return anything.
 ;
 
-UNINSTALL:
-        rts
+UNINSTALL:      rts
 
 
 ; ------------------------------------------------------------------------
 ; COUNT: Return the total number of available joysticks in a/x.
 ;
 
-COUNT:
-        lda     #<JOY_COUNT
-        ldx     #>JOY_COUNT
-        rts
+COUNT:          lda     #<JOY_COUNT
+                ldx     #>JOY_COUNT
+                rts
 
 ; ------------------------------------------------------------------------
 ; READ: Read a particular joystick passed in A.
 ;
 
-READJOY:
-        and     #1                      ; fix joystick number
-        bne     READJOY_1               ; read right joystick
+READJOY:        and     #1                      ; fix joystick number
+                bne     READJOY_1               ; read right joystick
 
 ; Read left joystick
 
-        ldx     ZP_JOY0_DIR
-        lda     ZP_JOY0_BUTTONS
-        jmp     convert                 ; convert joystick state to sane cc65 values
+                ldx     ZP_JOY0_DIR
+                lda     ZP_JOY0_BUTTONS
+                jmp     convert                 ; convert joystick state to cc65 values
 
 ; Read right joystick
 
-READJOY_1:
-
-        ldx     ZP_JOY1_DIR
-        lda     ZP_JOY1_BUTTONS
-        lsr     a
-        lsr     a
-        ;jmp    convert                 ; convert joystick state to sane cc65 values
-                                        ; fall thru...
+READJOY_1:      ldx     ZP_JOY1_DIR
+                lda     ZP_JOY1_BUTTONS
+                lsr     a
+                lsr     a
+                ;jmp    convert                 ; convert joystick state to cc65 values
+                                                ; fall thru...
 
 ; ------------------------------------------------------------------------
 ; convert: make runtime lib compatible values
-;       A - buttons
-;       X - direction
+;       inputs:
+;               A - buttons
+;               X - direction
 ;
 
 convert:
-        ldy     #0
-        sty     retval                  ; initialize return value
 
 ; ------
 ; buttons:
-        ; Port values are for the left hand joystick (right hand joystick
-        ; values were shifted to the right to be identical).
-        ; Why are there two bits indicating a pressed trigger?
-        ; According to the "Second book of programs for the Dick Smith Wizard"
-        ; (pg. 88ff), the left hand fire button gives the value of
-        ; %00010001 and the right hand button gives %00100010
-        ; Why two bits? Am I missing something? Can there be cases that just
-        ; one of those bits is set?
-        ; We just test if any of those two bits is not zero...
-
-        tay
-        and     #%00010001
-        beq     cnv_1
-
-        inc     retval                  ; left button pressed
-
-cnv_1:  tya
-        and     #%00100010
-        beq     cnv_2
-
-        lda     #$02
-        ora     retval
-        sta     retval                  ; right button pressed
+; Port values are for the left hand joystick (right hand joystick
+; values were shifted to the right to be identical).
+; Why are there two bits indicating a pressed trigger?
+; According to the "Second book of programs for the Dick Smith Wizard"
+; (pg. 88ff), the left hand fire button gives the value of
+; %00010001 and the right hand button gives %00100010
+; Why two bits? Can there be cases that just one of those bits is set?
+; Until these questions have been answered, we only use the lower two
+; bits and ignore the upper ones...
+
+                and     #%00000011              ; button status came in in A, strip high bits
+                sta     retval                  ; initialize 'retval' with button status
 
 ; ------
 ; direction:
-cnv_2:  txa
-        ; tested with https://sourceforge.net/projects/creativisionemulator
-        ; $49 - %01001001 - up
-        ; $41 - %01000001 - down
-        ; $4D - %01001101 - left
-        ; $45 - %01000101 - right
-        ;
-        ; are these correct? "Second book of programs for the Dick Smith Wizard" pg. 85 says something different
-        ; ignored for now...
-        ; $85 - %10000101 - up + right
-        ; $8D - %10001101 - down + left
-        ; $89 - %10001001 - up + left
-        ; $85 - %10000101 - down + right (emulator bug?)
-
-        bit     testbit                 ; bit #0 set?
-        beq     done                    ; no, no direction
-
-        and     #%00001100              ; mask out other bits
-        lsr     a
-        lsr     a
-        tax
-        lda     #%00000100              ; init bitmask
-loop:   dex
-        bmi     done2
-        asl     a
-        bne     loop
-
-done2:  ora     retval
-        rts
-
-done:   lda     retval
-        rts
+; CV has a 16-direction joystick
+;
+; port values: (compass points)
+; N      -  $49 - %01001001
+; NNE    -  $48 - %01001000
+; NE     -  $47 - %01000111
+; ENE    -  $46 - %01000110
+; E      -  $45 - %01000101
+; ESE    -  $44 - %01000100
+; SE     -  $43 - %01000011
+; SSE    -  $42 - %01000010
+; S      -  $41 - %01000001
+; SSW    -  $40 - %01000000
+; SW     -  $4F - %01001111
+; WSW    -  $4E - %01001110
+; W      -  $4D - %01001101
+; WNW    -  $4C - %01001100
+; NW     -  $4B - %01001011
+; NNW    -  $4A - %01001010
+; center -  $00 - %00000000
+;
+; mapping to cc65 definitions (4-direction joystick with 8 possible directions thru combinations)
+; N, E, S, W            ->      JOY_UP, JOY_RIGHT, JOY_DOWN, JOY_LEFT
+; NE, SE, SW, NW        ->      (JOY_UP | JOY_RIGHT), (JOY_DOWN | JOY_RIGHT), (JOY_DOWN | JOY_LEFT), (JOY_UP | JOY_LEFT)
+; NNE, ENE, ESE, SSE, SSW, WSW, WNW, NNW:
+;  toggle between straight and diagonal direction for every call, e.g.
+;  NNE:
+;    call to READJOY:   return JOY_UP | JOY_RIGHT
+;    call to READJOY:   return JOY_UP
+;    call to READJOY:   return JOY_UP | JOY_RIGHT
+;    call to READJOY:   return JOY_UP
+;    call to READJOY:   return JOY_UP | JOY_RIGHT
+;    etc...
+
+                txa                             ; move direction status into A
+                beq     done                    ; center position (no bits are set), nothing to do
+
+                and     #$0F                    ; get rid of the "$40" bit
+                bit     bit0                    ; is it a "three letter" direction (NNE, ENE, etc.)?
+                beq     special                 ; yes (bit #0 is zero)
+
+                lsr     a                       ; create index into table
+                tax
+                lda     dirtable,x
+done:           ora     retval                  ; include "button" bits
+                ldx     #0
+                rts
+
+; NNE, ENE, ESE, SSE, SSW, WSW, WNW, NNW
+
+special:        lsr     a
+                tax
+
+                lda     toggler                 ; toggle the toggler
+                eor     #$01
+                sta     toggler
+                bne     spec_1                  ; toggler is 1, use spectable_1 entry
+
+                lda     spectable_0,x           ; toggler is 0, use spectable_0 entry
+                bne     done                    ; jump always
+
+spec_1:         lda     spectable_1,x
+                bne     done                    ; jump always
 
 ; ------------------------------------------------------------------------
 ;
-        .data
-testbit:.byte   $01
+                .rodata
+
+                ; a mapping table of "port values" to "cc65 values"
+                ; port value had been shifted one bit to the right (range 0..7)
+dirtable:       .byte   JOY_DOWN                ; S
+                .byte   JOY_DOWN | JOY_RIGHT    ; SE
+                .byte   JOY_RIGHT               ; E
+                .byte   JOY_UP   | JOY_RIGHT    ; NE
+                .byte   JOY_UP                  ; N
+                .byte   JOY_UP   | JOY_LEFT     ; NW
+                .byte   JOY_LEFT                ; W
+                .byte   JOY_DOWN | JOY_LEFT     ; SW
+
+                ; two "special" mapping tables for three-letter directions (NNE, etc.)
+spectable_0:    .byte   JOY_DOWN                ; SSW
+                .byte   JOY_DOWN                ; SSE
+                .byte   JOY_RIGHT               ; ESE
+                .byte   JOY_RIGHT               ; ENE
+                .byte   JOY_RIGHT               ; NNE
+                .byte   JOY_UP                  ; NNW
+                .byte   JOY_LEFT                ; WNW
+                .byte   JOY_LEFT                ; WSW
+
+spectable_1:    .byte   JOY_DOWN | JOY_LEFT     ; SSW
+                .byte   JOY_DOWN | JOY_RIGHT    ; SSE
+                .byte   JOY_DOWN | JOY_RIGHT    ; ESE
+                .byte   JOY_UP   | JOY_RIGHT    ; ENE
+                .byte   JOY_UP   | JOY_RIGHT    ; NNE
+                .byte   JOY_UP   | JOY_LEFT     ; NNW
+                .byte   JOY_UP   | JOY_LEFT     ; WNW
+                .byte   JOY_DOWN | JOY_LEFT     ; WSW
 
 ; ------------------------------------------------------------------------
 ;
-        .bss
-retval: .res    0
+bit0:           .byte   $01
+
+; ------------------------------------------------------------------------
+;
+                .bss
+toggler:        .res    1
+retval:         .res    1
+
+                .end
diff --git a/libsrc/creativision/mainargs.s b/libsrc/creativision/mainargs.s
deleted file mode 100644 (file)
index cda76d8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-;
-; Ullrich von Bassewitz, 2003-03-07
-;
-; Setup arguments for main
-;
-
-
-        .constructor    initmainargs, 24
-        .import         __argc, __argv
-
-
-;---------------------------------------------------------------------------
-; Get possible command-line arguments. Goes into the special INIT segment,
-; which may be reused after the startup code is run
-
-.segment        "INIT"
-
-.proc   initmainargs
-
-        rts
-
-.endproc
index 9161645c77899bd30334ba5f4adc86f26f34e56c..f05ad33e014c8a1e7e6df55a3abe0a7bb2c24d2f 100644 (file)
@@ -1,50 +1,50 @@
-;\r
-; char cgetc (void);\r
-;\r
-\r
-        .constructor    initcgetc\r
-        .export         _cgetc\r
-        .import         cursor\r
-\r
-        .include        "osic1p.inc"\r
-        .include        "extzp.inc"\r
-        .include        "zeropage.inc"\r
-\r
-; Initialize one-character buffer that is filled by kbhit()\r
-        .segment        "ONCE"\r
-initcgetc:\r
-        lda     #$00\r
-        sta     CHARBUF         ; No character in buffer initially\r
-        rts\r
-\r
-; Input routine from 65V PROM MONITOR, show cursor if enabled\r
-        .code\r
-_cgetc:\r
-        lda     CHARBUF         ; character in buffer available?\r
-        beq     nobuffer\r
-        tax                     ; save character in X\r
-        lda     #$00\r
-        sta     CHARBUF         ; empty buffer\r
-        beq     restorex        ; restore X and return\r
-nobuffer:\r
-        lda     cursor          ; show cursor?\r
-        beq     nocursor\r
-        ldy     CURS_X\r
-        lda     (SCREEN_PTR),y  ; fetch current character\r
-        sta     tmp1            ; save it\r
-        lda     #$A1            ; full white square\r
-        sta     (SCREEN_PTR),y  ; store at cursor position\r
-nocursor:\r
-        jsr     INPUTC          ; get input character in A\r
-        ldx     cursor\r
-        beq     done            ; was cursor on?\r
-        tax                     ; save A in X\r
-        lda     tmp1            ; fetch saved character\r
-        ldy     CURS_X\r
-        sta     (SCREEN_PTR),y  ; store at cursor position\r
-\r
-restorex:\r
-        txa                     ; restore saved character from X\r
-done:\r
-        ldx     #$00            ; high byte of int return value\r
-        rts\r
+;
+; char cgetc (void);
+;
+
+        .constructor    initcgetc
+        .export         _cgetc
+        .import         cursor
+
+        .include        "osic1p.inc"
+        .include        "extzp.inc"
+        .include        "zeropage.inc"
+
+; Initialize one-character buffer that is filled by kbhit()
+        .segment        "ONCE"
+initcgetc:
+        lda     #$00
+        sta     CHARBUF         ; No character in buffer initially
+        rts
+
+; Input routine from 65V PROM MONITOR, show cursor if enabled
+        .code
+_cgetc:
+        lda     CHARBUF         ; character in buffer available?
+        beq     nobuffer
+        tax                     ; save character in X
+        lda     #$00
+        sta     CHARBUF         ; empty buffer
+        beq     restorex        ; restore X and return
+nobuffer:
+        lda     cursor          ; show cursor?
+        beq     nocursor
+        ldy     CURS_X
+        lda     (SCREEN_PTR),y  ; fetch current character
+        sta     tmp1            ; save it
+        lda     #$A1            ; full white square
+        sta     (SCREEN_PTR),y  ; store at cursor position
+nocursor:
+        jsr     INPUTC          ; get input character in A
+        ldx     cursor
+        beq     done            ; was cursor on?
+        tax                     ; save A in X
+        lda     tmp1            ; fetch saved character
+        ldy     CURS_X
+        sta     (SCREEN_PTR),y  ; store at cursor position
+
+restorex:
+        txa                     ; restore saved character from X
+done:
+        ldx     #$00            ; high byte of int return value
+        rts
index eabeaf79e7ea61cae53ab85ee6adf3180f128f04..aaa03ba6189a05b56ddffdbf0ddbe87b85c29ecf 100644 (file)
@@ -1,4 +1,4 @@
-; Addresses\r
-INPUTC          := $FD00        ; Input character from keyboard\r
-RESET           := $FF00        ; Reset address, show boot prompt\r
-KBD             := $DF00        ; Polled keyboard register\r
+; Addresses
+INPUTC          := $FD00        ; Input character from keyboard
+RESET           := $FF00        ; Reset address, show boot prompt
+KBD             := $DF00        ; Polled keyboard register
index fc832478199a2fd821dd42562c65a7f0ba647fb4..9399d7eee073f11b169dc6d48ea8e77250c812ea 100644 (file)
-;\r
-; Macro definitions for screen layout modules\r
-;\r
-\r
-        .include        "extzp.inc"\r
-        \r
-.linecont +\r
-\r
-;\r
-; Internal function for screensize()\r
-;\r
-.macro  osi_screensize ScrWidth, ScrHeight\r
-                                ; Macro implementation of internal screensize\r
-                                ; function for given width and height in\r
-                                ; characters\r
-                                \r
-        .export         screensize\r
-\r
-.proc   screensize\r
-        ldx     #ScrWidth\r
-        ldy     #ScrHeight\r
-        rts\r
-.endproc\r
-.endmacro\r
-\r
-;\r
-; void clrscr (void);\r
-;\r
-.macro  osi_clrscr ScrBase, ScrRamSize\r
-\r
-        .export         _clrscr\r
-\r
-.proc   _clrscr\r
-        lda     #<ScrBase       ; Fill whole video RAM with blanks by calling\r
-        ldx     #>ScrBase       ; memset appropriately\r
-        jsr     pushax\r
-        \r
-        lda     #' '\r
-        ldx     #$00\r
-        jsr     pushax\r
-        \r
-        lda     #<ScrRamSize\r
-        ldx     #>ScrRamSize\r
-        jsr     _memset\r
-\r
-        lda     #$00            ; Cursor in upper left corner\r
-        sta     CURS_X\r
-        sta     CURS_Y\r
-        \r
-        jmp     plot            ; Set the cursor position\r
-.endproc\r
-\r
-.endmacro\r
-\r
-;\r
-; cputc/cputcxy for Challenger 1P\r
-; Based on PET/CBM implementation\r
-;\r
-\r
-.macro  osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \\r
-                         ScrollDist, ScrLo, ScrHi\r
-\r
-                                ; Number of characters to move for scrolling\r
-                                ; by one line\r
-ScrollLength    = (ScrHeight - 1) * ScrollDist\r
-\r
-;\r
-; void cputcxy (unsigned char x, unsigned char y, char c);\r
-; void cputc (char c);\r
-;\r
-        .export         _cputcxy, _cputc, cputdirect, putchar\r
-        .export         newline, plot\r
-\r
-_cputcxy:\r
-        pha                     ; Save C\r
-        jsr     gotoxy          ; Set cursor, drop x and y\r
-        pla                     ; Restore C\r
-\r
-; Plot a character - also used as internal function\r
-\r
-_cputc: cmp     #$0A            ; CR?\r
-        bne     L1\r
-        lda     #0\r
-        sta     CURS_X\r
-        beq     plot            ; Recalculate pointers\r
-\r
-L1:     cmp     #$0D            ; LF?\r
-        beq     newline         ; Recalculate pointers\r
-\r
-cputdirect:\r
-        jsr     putchar         ; Write the character to the screen\r
-\r
-; Advance cursor position, register Y contains horizontal position after\r
-; putchar\r
-\r
-        cpy     #(ScrWidth - 1) ; Check whether line is full\r
-        bne     L3\r
-        jsr     newline         ; New line\r
-        ldy     #$FF            ; + cr\r
-L3:     iny\r
-        sty     CURS_X\r
-        rts\r
-\r
-newline:\r
-        inc     CURS_Y\r
-        lda     CURS_Y\r
-        cmp     #ScrHeight      ; Screen height\r
-        bne     plot\r
-        dec     CURS_Y          ; Bottom of screen reached, scroll\r
-\r
-                                ; Scroll destination address\r
-        lda     #<(ScrBase + ScrFirstChar)\r
-        ldx     #>(ScrBase + ScrFirstChar)\r
-        jsr     pushax\r
-        \r
-                                ; Scroll source address\r
-        lda     #<(ScrBase + ScrFirstChar + ScrollDist)\r
-        ldx     #>(ScrBase + ScrFirstChar + ScrollDist)\r
-        jsr     pushax\r
-        \r
-                                ; Number of characters to move\r
-        lda     #<ScrollLength\r
-        ldx     #>ScrollLength\r
-        jsr     _memmove\r
-\r
-                                ; Address of first character in last line\r
-                                ; of screen\r
-        lda     #<(ScrBase + ScrFirstChar + ScrollLength)\r
-        sta     ptr1\r
-        lda     #>(ScrBase + ScrFirstChar + ScrollLength)\r
-        sta     ptr1+1\r
-        \r
-        ldy     #ScrWidth       ; Fill last line with blanks\r
-        lda     #' '\r
-clrln:  sta     (ptr1),y\r
-        dey\r
-        bpl     clrln\r
-\r
-plot:   ldy     CURS_Y\r
-        lda     ScrLo,y\r
-        sta     SCREEN_PTR\r
-        lda     ScrHi,y\r
-        sta     SCREEN_PTR+1\r
-        rts\r
-\r
-; Write one character to the screen without doing anything else, return X\r
-; position in register Y\r
-\r
-putchar:\r
-        ldy     CURS_X\r
-        sta     (SCREEN_PTR),y  ; Set char\r
-        rts\r
-        \r
-.endmacro\r
-\r
-.macro osi_screen_funcs ScrBase, ScrRamSize, ScrFirstChar, \\r
-                        ScrWidth, ScrHeight, ScrollDist\r
-\r
-        .import         gotoxy\r
-        .import         _memmove, _memset, pushax\r
-        .importzp       ptr1\r
-\r
-.rodata\r
-\r
-; Screen address tables - offset to real screen\r
-ScrTabLo:\r
-        .repeat ScrHeight, I\r
-        .byte <(ScrBase + ScrFirstChar + I * ScrollDist)\r
-        .endrep\r
-        \r
-ScrTabHi:\r
-        .repeat ScrHeight, I\r
-        .byte >(ScrBase + ScrFirstChar + I * ScrollDist)\r
-        .endrep\r
-\r
-.code\r
-\r
-osi_cputfuncs   ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \\r
-                         ScrollDist, ScrTabLo, ScrTabHi\r
-osi_screensize  ScrWidth, ScrHeight\r
-osi_clrscr      ScrBase, ScrRamSize\r
-\r
+;
+; Macro definitions for screen layout modules
+;
+
+        .include        "extzp.inc"
+        
+.linecont +
+
+;
+; Internal function for screensize()
+;
+.macro  osi_screensize ScrWidth, ScrHeight
+                                ; Macro implementation of internal screensize
+                                ; function for given width and height in
+                                ; characters
+                                
+        .export         screensize
+
+.proc   screensize
+        ldx     #ScrWidth
+        ldy     #ScrHeight
+        rts
+.endproc
+.endmacro
+
+;
+; void clrscr (void);
+;
+.macro  osi_clrscr ScrBase, ScrRamSize
+
+        .export         _clrscr
+
+.proc   _clrscr
+        lda     #<ScrBase       ; Fill whole video RAM with blanks by calling
+        ldx     #>ScrBase       ; memset appropriately
+        jsr     pushax
+        
+        lda     #' '
+        ldx     #$00
+        jsr     pushax
+        
+        lda     #<ScrRamSize
+        ldx     #>ScrRamSize
+        jsr     _memset
+
+        lda     #$00            ; Cursor in upper left corner
+        sta     CURS_X
+        sta     CURS_Y
+        
+        jmp     plot            ; Set the cursor position
+.endproc
+
+.endmacro
+
+;
+; cputc/cputcxy for Challenger 1P
+; Based on PET/CBM implementation
+;
+
+.macro  osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \
+                         ScrollDist, ScrLo, ScrHi
+
+                                ; Number of characters to move for scrolling
+                                ; by one line
+ScrollLength    = (ScrHeight - 1) * ScrollDist
+
+;
+; void cputcxy (unsigned char x, unsigned char y, char c);
+; void cputc (char c);
+;
+        .export         _cputcxy, _cputc, cputdirect, putchar
+        .export         newline, plot
+
+_cputcxy:
+        pha                     ; Save C
+        jsr     gotoxy          ; Set cursor, drop x and y
+        pla                     ; Restore C
+
+; Plot a character - also used as internal function
+
+_cputc: cmp     #$0A            ; CR?
+        bne     L1
+        lda     #0
+        sta     CURS_X
+        beq     plot            ; Recalculate pointers
+
+L1:     cmp     #$0D            ; LF?
+        beq     newline         ; Recalculate pointers
+
+cputdirect:
+        jsr     putchar         ; Write the character to the screen
+
+; Advance cursor position, register Y contains horizontal position after
+; putchar
+
+        cpy     #(ScrWidth - 1) ; Check whether line is full
+        bne     L3
+        jsr     newline         ; New line
+        ldy     #$FF            ; + cr
+L3:     iny
+        sty     CURS_X
+        rts
+
+newline:
+        inc     CURS_Y
+        lda     CURS_Y
+        cmp     #ScrHeight      ; Screen height
+        bne     plot
+        dec     CURS_Y          ; Bottom of screen reached, scroll
+
+                                ; Scroll destination address
+        lda     #<(ScrBase + ScrFirstChar)
+        ldx     #>(ScrBase + ScrFirstChar)
+        jsr     pushax
+        
+                                ; Scroll source address
+        lda     #<(ScrBase + ScrFirstChar + ScrollDist)
+        ldx     #>(ScrBase + ScrFirstChar + ScrollDist)
+        jsr     pushax
+        
+                                ; Number of characters to move
+        lda     #<ScrollLength
+        ldx     #>ScrollLength
+        jsr     _memmove
+
+                                ; Address of first character in last line
+                                ; of screen
+        lda     #<(ScrBase + ScrFirstChar + ScrollLength)
+        sta     ptr1
+        lda     #>(ScrBase + ScrFirstChar + ScrollLength)
+        sta     ptr1+1
+        
+        ldy     #ScrWidth       ; Fill last line with blanks
+        lda     #' '
+clrln:  sta     (ptr1),y
+        dey
+        bpl     clrln
+
+plot:   ldy     CURS_Y
+        lda     ScrLo,y
+        sta     SCREEN_PTR
+        lda     ScrHi,y
+        sta     SCREEN_PTR+1
+        rts
+
+; Write one character to the screen without doing anything else, return X
+; position in register Y
+
+putchar:
+        ldy     CURS_X
+        sta     (SCREEN_PTR),y  ; Set char
+        rts
+        
+.endmacro
+
+.macro osi_screen_funcs ScrBase, ScrRamSize, ScrFirstChar, \
+                        ScrWidth, ScrHeight, ScrollDist
+
+        .import         gotoxy
+        .import         _memmove, _memset, pushax
+        .importzp       ptr1
+
+.rodata
+
+; Screen address tables - offset to real screen
+ScrTabLo:
+        .repeat ScrHeight, I
+        .byte <(ScrBase + ScrFirstChar + I * ScrollDist)
+        .endrep
+        
+ScrTabHi:
+        .repeat ScrHeight, I
+        .byte >(ScrBase + ScrFirstChar + I * ScrollDist)
+        .endrep
+
+.code
+
+osi_cputfuncs   ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \
+                         ScrollDist, ScrTabLo, ScrTabHi
+osi_screensize  ScrWidth, ScrHeight
+osi_clrscr      ScrBase, ScrRamSize
+
 .endmacro
\ No newline at end of file
diff --git a/libsrc/telestrat/clrscr.s b/libsrc/telestrat/clrscr.s
new file mode 100644 (file)
index 0000000..f2b8faf
--- /dev/null
@@ -0,0 +1,35 @@
+;
+; jede jede@oric.org 2017-02-25
+; 
+
+    .export    _clrscr
+       
+    .importzp  sp
+       
+    .include   "telestrat.inc"
+
+.proc _clrscr
+    lda     #<SCREEN
+    ldy     #>SCREEN
+    sta     RES
+    sty     RES+1
+
+    ldy     #<(SCREEN+SCREEN_XSIZE*SCREEN_YSIZE)
+    ldx     #>(SCREEN+SCREEN_XSIZE*SCREEN_YSIZE)
+    lda     #' '
+    BRK_TELEMON XFILLM
+       
+       
+    ; reset prompt position
+    lda     #<(SCREEN+40)
+    sta     ADSCRL
+    lda     #>(SCREEN+40)
+    sta     ADSCRH
+       
+    ; reset display position
+    lda     #$01
+    sta     SCRY
+    lda     #$00
+    sta     SCRX       
+    rts
+.endproc       
diff --git a/libsrc/telestrat/gotox.s b/libsrc/telestrat/gotox.s
new file mode 100644 (file)
index 0000000..d6af0e4
--- /dev/null
@@ -0,0 +1,16 @@
+;
+; jede jede@oric.org 2017-02-25
+;
+    .export    _gotox
+       
+    .import    popa
+       
+    .importzp  sp
+
+    .include   "telestrat.inc"
+
+
+.proc _gotox
+   sta    SCRX
+   rts
+.endproc       
diff --git a/libsrc/telestrat/gotoxy.s b/libsrc/telestrat/gotoxy.s
new file mode 100644 (file)
index 0000000..e0c8154
--- /dev/null
@@ -0,0 +1,19 @@
+;
+; jede jede@oric.org 2017-02-25
+;
+    .export    _gotoxy
+       
+    .import    popa
+       
+    .importzp  sp
+
+    .include   "telestrat.inc"
+
+.proc _gotoxy
+   ; This function move only cursor for display, it does not move the prompt position
+   ; in telemon, there is position for prompt, and another for the cursor
+   sta    SCRY
+   jsr    popa
+   sta    SCRX
+   rts
+.endproc       
diff --git a/libsrc/telestrat/gotoy.s b/libsrc/telestrat/gotoy.s
new file mode 100644 (file)
index 0000000..ed7101c
--- /dev/null
@@ -0,0 +1,13 @@
+;
+; jede jede@oric.org 2017-02-25
+;
+    .export    _gotoy
+
+    .importzp  sp
+
+    .include   "telestrat.inc"
+
+.proc _gotoy
+   sta     SCRY
+   rts
+.endproc       
diff --git a/libsrc/telestrat/wherex.s b/libsrc/telestrat/wherex.s
new file mode 100644 (file)
index 0000000..0dd5139
--- /dev/null
@@ -0,0 +1,14 @@
+;
+; jede jede@oric.org 2017-02-25
+;
+    .export    _wherex
+       
+    .importzp  sp
+
+    .include   "telestrat.inc"
+
+.proc _wherex
+    ldx    #$00
+    lda    SCRX
+    rts
+.endproc       
diff --git a/libsrc/telestrat/wherey.s b/libsrc/telestrat/wherey.s
new file mode 100644 (file)
index 0000000..4958f10
--- /dev/null
@@ -0,0 +1,14 @@
+;
+; jede jede@oric.org 2017-02-25
+; 
+    .export    _wherey
+       
+    .importzp  sp
+
+    .include   "telestrat.inc"
+
+.proc _wherey
+    ldx    #$00
+    lda    SCRY
+    rts
+.endproc       
index edfeca689c42ff1b92823474d3266110f0e0bd8d..94994002224dd425bb977f1416098bce15233c8a 100644 (file)
@@ -90,7 +90,7 @@ LDFLAGS_tgidemo_atarixl    = --start-addr 0x4000
 %: %.s
 
 .c.o:
-       $(CC) $(CFLAGS) -Oirs --codesize 500 -T -g -t $(SYS) $<
+       $(CC) $(CFLAGS) -Ors --codesize 500 -T -g -t $(SYS) $<
        $(AS) $(<:.c=.s)
 
 .s.o:
index 9f1ab29f55a0a89d1945f8e649f11ccd357364cb..48a5c29d35adca95c566a0adf9f490b041ffbab9 100644 (file)
@@ -157,7 +157,7 @@ static void Parse (void)
                   CurTok.Tok == TOK_ASSIGN))) {
 
                 /* We will allocate storage */
-                Decl.StorageClass |= SC_STORAGE | SC_DEF;
+                Decl.StorageClass |= SC_STORAGE;
             }
 
             /* If this is a function declarator that is not followed by a comma
@@ -190,6 +190,13 @@ static void Parse (void)
                 /* Allow initialization */
                 if (CurTok.Tok == TOK_ASSIGN) {
 
+                    /* This is a definition */
+                    if (SymIsDef (Entry)) {
+                        Error ("Global variable `%s' has already been defined",
+                               Entry->Name);
+                    }
+                    Entry->Flags |= SC_DEF;
+
                     /* We cannot initialize types of unknown size, or
                     ** void types in ISO modes.
                     */
@@ -237,18 +244,14 @@ static void Parse (void)
                         Entry->Flags &= ~(SC_STORAGE | SC_DEF);
                     }
 
-                    /* Allocate storage if it is still needed */
-                    if (Entry->Flags & SC_STORAGE) {
-
-                        /* Switch to the BSS segment */
-                        g_usebss ();
-
-                        /* Define a label */
-                        g_defgloblabel (Entry->Name);
-
-                        /* Allocate space for uninitialized variable */
-                        g_res (Size);
-                    }
+                    /* A global (including static) uninitialized variable
+                    ** is only a tentative definition. For example, this is valid:
+                    ** int i;
+                    ** int i;
+                    ** static int j;
+                    ** static int j = 42;
+                    ** Code for these will be generated in FinishCompile.
+                    */
                 }
 
             }
@@ -303,7 +306,7 @@ void Compile (const char* FileName)
     struct tm*  TM;
 
     /* Since strftime is locale dependent, we need the abbreviated month names
-    ** in english.
+    ** in English.
     */
     static const char MonthNames[12][4] = {
         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -400,20 +403,26 @@ void Compile (const char* FileName)
 void FinishCompile (void)
 /* Emit literals, externals, debug info, do cleanup and optimizations */
 {
-    SymTable* SymTab;
-    SymEntry* Func;
-
-    /* Walk over all functions, doing cleanup, optimizations ... */
-    SymTab = GetGlobalSymTab ();
-    Func   = SymTab->SymHead;
-    while (Func) {
-        if (SymIsOutputFunc (Func)) {
+    SymEntry* Entry;
+
+    /* Walk over all global symbols:
+    ** - for functions do cleanup, optimizations ...
+    ** - generate code for uninitialized global variables
+    */
+    for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
+        if (SymIsOutputFunc (Entry)) {
             /* Function which is defined and referenced or extern */
-            MoveLiteralPool (Func->V.F.LitPool);
-            CS_MergeLabels (Func->V.F.Seg->Code);
-            RunOpt (Func->V.F.Seg->Code);
+            MoveLiteralPool (Entry->V.F.LitPool);
+            CS_MergeLabels (Entry->V.F.Seg->Code);
+            RunOpt (Entry->V.F.Seg->Code);
+        } else if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
+            /* Tentative definition of uninitialized global variable */
+            g_usebss ();
+            g_defgloblabel (Entry->Name);
+            g_res (SizeOf (Entry->Type));
+            /* Mark as defined, so that it will be exported not imported */
+            Entry->Flags |= SC_DEF;
         }
-        Func = Func->NextSym;
     }
 
     /* Output the literal pool */
index 8c9d6dcb00d6feb81cf12b7b2cc28316d7023c8f..2d54316cd9cbba88b28f97773107e48c8e132cac 100644 (file)
@@ -389,7 +389,10 @@ unsigned SizeOf (const Type* T)
     switch (UnqualifiedType (T->C)) {
 
         case T_VOID:
-            return 0;   /* Assume voids have size zero */
+            /* A void variable is a cc65 extension.
+            ** Get its size (in bytes).
+            */
+            return T->A.U;
 
         /* Beware: There's a chance that this triggers problems in other parts
            of the compiler. The solution is to fix the callers, because calling
@@ -438,7 +441,7 @@ unsigned SizeOf (const Type* T)
                 /* Array with unspecified size */
                 return 0;
             } else {
-                return T->A.L * SizeOf (T + 1);
+                return T->A.U * SizeOf (T + 1);
             }
 
         default:
index 1630848350892bafc71df8006490d3720c8e35c9..7b543aa55aa913c52ac21af66656a273c61021f6 100644 (file)
@@ -891,6 +891,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
         case TOK_VOID:
             NextToken ();
             D->Type[0].C = T_VOID;
+            D->Type[0].A.U = 0;
             D->Type[1].C = T_END;
             break;
 
@@ -2114,7 +2115,7 @@ NextMember:
 
 
 
-static unsigned ParseVoidInit (void)
+static unsigned ParseVoidInit (Type* T)
 /* Parse an initialization of a void variable (special cc65 extension).
 ** Return the number of bytes initialized.
 */
@@ -2181,6 +2182,9 @@ static unsigned ParseVoidInit (void)
     /* Closing brace */
     ConsumeRCurly ();
 
+    /* Number of bytes determined by initializer */
+    T->A.U = Size;
+
     /* Return the number of bytes initialized */
     return Size;
 }
@@ -2216,8 +2220,8 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers)
 
         case T_VOID:
             if (IS_Get (&Standard) == STD_CC65) {
-                /* Special cc65 extension in non ANSI mode */
-                return ParseVoidInit ();
+                /* Special cc65 extension in non-ANSI mode */
+                return ParseVoidInit (T);
             }
             /* FALLTHROUGH */
 
index fdf45987370581f3d833104d92f937c4080b7d70..3275332c5490c68b89ab7a5c4b6e560716574144 100644 (file)
@@ -821,7 +821,7 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
         }
 
         /* An extern declaration must not change the current linkage. */
-        if (IsFunc || (Flags & (SC_EXTERN | SC_DEF)) == SC_EXTERN) {
+        if (IsFunc || (Flags & (SC_EXTERN | SC_STORAGE)) == SC_EXTERN) {
             Flags &= ~SC_EXTERN;
         }
 
diff --git a/test/err/duplicate-global-static.c b/test/err/duplicate-global-static.c
new file mode 100644 (file)
index 0000000..6aa27f5
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+  !!DESCRIPTION!! global duplicated with static variable
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Piotr Fusik
+*/
+
+/*
+  see: https://github.com/cc65/cc65/issues/191
+*/
+
+int n = 0;
+static int n = 0;           /* should give an error */
+
+int main(void)
+{
+    return n;
+}
diff --git a/test/err/duplicate-global.c b/test/err/duplicate-global.c
new file mode 100644 (file)
index 0000000..bd4fcc2
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+  !!DESCRIPTION!! duplicate globals
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Piotr Fusik
+*/
+
+/*
+  see: https://github.com/cc65/cc65/issues/191
+*/
+
+#pragma warn(error, on)
+
+int n = 0;
+int n = 0;           /* should give an error */
+
+int main(void)
+{
+    return n;
+}
diff --git a/test/err/duplicate-static-global.c b/test/err/duplicate-static-global.c
new file mode 100644 (file)
index 0000000..6e5e70a
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+  !!DESCRIPTION!! static duplicated with global variable
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Piotr Fusik
+*/
+
+/*
+  see: https://github.com/cc65/cc65/issues/191
+*/
+
+static int n = 0;
+int n = 0;           /* should give an error */
+
+int main(void)
+{
+    return n;
+}
diff --git a/test/err/duplicate-static.c b/test/err/duplicate-static.c
new file mode 100644 (file)
index 0000000..394cc1e
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+  !!DESCRIPTION!! duplicate static variables
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Piotr Fusik
+*/
+
+/*
+  see: https://github.com/cc65/cc65/issues/191
+*/
+
+#pragma warn(error, on)
+
+static int n = 0;
+static int n = 0;           /* should give an error */
+
+int main(void)
+{
+    return n;
+}
diff --git a/test/err/void-empty.c b/test/err/void-empty.c
new file mode 100644 (file)
index 0000000..9009182
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+  !!DESCRIPTION!! Uninitialized void variables
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Greg King
+*/
+
+void test;
+const void list;
diff --git a/test/err/void-size2.c b/test/err/void-size2.c
new file mode 100644 (file)
index 0000000..3d4f133
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+  !!DESCRIPTION!! Size of void cast
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Greg King
+*/
+
+unsigned test (void)
+{
+    return sizeof ((void)12345);
+}
index 09dd96d4425455f290c50a165751835c50d64576..6f0bd1bc14dcfdbfab1900e9d82d8c4c17869b97 100644 (file)
@@ -1,4 +1,3 @@
-
 # makefile for the regression tests that generate output which has to be
 # compared with reference output
 
@@ -24,7 +23,7 @@ WORKDIR := ..$S..$Stestwrk
 DIFF := $(WORKDIR)/bdiff
 
 CC := gcc
-CFLAGS := -O2 -Wall -W -Wextra -fwrapv -fno-strict-overflow
+CFLAGS := -O2 -Wall -W -Wextra -funsigned-char -fwrapv -fno-strict-overflow
 
 .PHONY: all clean
 
@@ -34,6 +33,11 @@ TESTS := $(foreach option,. .o. .os. .osi. .osir. .oi. .oir. .or.,$(SOURCES:%.c=
 
 all: $(REFS) $(TESTS)
 
+# "yaccdbg.c" includes "yacc.c".
+# yaccdbg's built files must depend on both of them.
+
+$(WORKDIR)/yaccdbg.ref: yacc.c
+
 $(WORKDIR)/%.ref: %.c
        $(CC) $(CFLAGS) $< -o $(WORKDIR)/$*.host
        $(WORKDIR)$S$*.host > $@
@@ -48,6 +52,8 @@ $(WORKDIR)/switch.%rg: CC65FLAGS += -Wc --all-cdecl
 $(WORKDIR)/yacc.%rg: CC65FLAGS += -Wc --all-cdecl
 $(WORKDIR)/yaccdbg%prg: CC65FLAGS += -Wc --all-cdecl
 
+$(WORKDIR)/yaccdbg%prg: yacc.c
+
 $(WORKDIR)/%.prg: %.c $(WORKDIR)/%.ref
        $(CL65) $(CC65FLAGS) $< -o $@
        $(SIM65) $(SIM65FLAGS) $@ > $(WORKDIR)/$*.out
index 68a0198e161ee37b4f976adfa32b6c5c6fad9c24..8fcc951a6ee2f44b07ec63564e9103b8282048fb 100644 (file)
@@ -1,38 +1,38 @@
-/*\r
-  !!DESCRIPTION!! div/mod test\r
-  !!ORIGIN!!\r
-  !!LICENCE!!     public domain\r
-*/\r
-\r
-#include <stdio.h>\r
-\r
-void printc(signed char a,signed char b){\r
-signed char x=a/b,y=a%b,z=a*b;\r
-       printf("%3d,%3d is %3d,%3d,%3d\n",a,b,x,y,z);\r
-}\r
-void prints(short a,short b){\r
-short x=a/b,y=a%b,z=a*b;\r
-       printf("%3d,%3d is %3d,%3d,%3d\n",a,b,x,y,z);\r
-}\r
-void printl(long a,long b){\r
-long x=a/b,y=a%b,z=a*b;\r
-       printf("%3ld,%3ld is %3ld,%3ld,%3ld\n",a,b,x,y,z);\r
-}\r
-\r
-int main(void) {\r
-       printl( 3,-2);\r
-       printl(-3,-2);\r
-       printl(-3, 2);\r
-       printl( 3, 2);\r
-       printf("-\n");\r
-       prints( 3,-2);\r
-       prints(-3,-2);\r
-       prints(-3, 2);\r
-       prints( 3, 2);\r
-       printf("-\n");\r
-       printc( 3,-2);\r
-       printc(-3,-2);\r
-       printc(-3, 2);\r
-       printc( 3, 2);\r
+/*
+  !!DESCRIPTION!! div/mod test
+  !!ORIGIN!!
+  !!LICENCE!!     public domain
+*/
+
+#include <stdio.h>
+
+void printc(signed char a,signed char b){
+signed char x=a/b,y=a%b,z=a*b;
+       printf("%3d,%3d is %3d,%3d,%3d\n",a,b,x,y,z);
+}
+void prints(short a,short b){
+short x=a/b,y=a%b,z=a*b;
+       printf("%3d,%3d is %3d,%3d,%3d\n",a,b,x,y,z);
+}
+void printl(long a,long b){
+long x=a/b,y=a%b,z=a*b;
+       printf("%3ld,%3ld is %3ld,%3ld,%3ld\n",a,b,x,y,z);
+}
+
+int main(void) {
+       printl( 3,-2);
+       printl(-3,-2);
+       printl(-3, 2);
+       printl( 3, 2);
+       printf("-\n");
+       prints( 3,-2);
+       prints(-3,-2);
+       prints(-3, 2);
+       prints( 3, 2);
+       printf("-\n");
+       printc( 3,-2);
+       printc(-3,-2);
+       printc(-3, 2);
+       printc( 3, 2);
        return 0;
-}\r
+}
index 5a581675318dc39af59782ce50ee09a94b810d9f..44cd544fd77d5128c5423278bd20d05041f854e7 100644 (file)
@@ -1,95 +1,95 @@
-/*\r
-  !!DESCRIPTION!! variable initialization\r
-  !!ORIGIN!!      LCC 4.1 Testsuite\r
-  !!LICENCE!!     own, freely distributeable for non-profit. read CPYRIGHT.LCC\r
-*/\r
-\r
-#include "common.h"\r
-/* todo: add back conditional stuff here ! */\r
-\r
-typedef struct { int codes[3]; char name[6]; } Word;\r
-\r
-#ifdef NO_IMPLICIT_FUNC_PROTOTYPES\r
-\r
-#ifdef NO_OLD_FUNC_DECL\r
-f();\r
-void g(Word *p);\r
-h();\r
-#else\r
-f();\r
-g();\r
-h();\r
-#endif\r
-\r
-#endif\r
-\r
-/*\r
-Word words[] = {\r
-        1, 2, 3,"if",\r
-       { { 4, 5 }, { 'f', 'o', 'r' } },\r
-        6, 7, 8, {"else"},\r
-        { { 9, 10, 11,}, 'w', 'h', 'i', 'l', 'e', },\r
-        { 0 },\r
-}, *wordlist = words;\r
-*/\r
-\r
-Word words[] = {\r
-        {{1, 2, 3},"if"},\r
-       { { 4, 5 }, { 'f', 'o', 'r' } },\r
-        {{6, 7, 8}, "else"},\r
-        { { 9, 10, 11}, {'w', 'h', 'i', 'l', 'e', }},\r
-        {{ 0 }},\r
-}, *wordlist = words;\r
-\r
-/*int x[][5] = { 1, 2, 3, 4, 0, { 5, 6 }, { 7 } };*/\r
-int x[][5] = { {1, 2, 3, 4, 0 }, { 5, 6 }, { 7 } };\r
-int *y[] = { x[0], x[1], x[2], 0 };\r
-\r
-main()\r
-{\r
-       int i, j;\r
-\r
-       for (i = 0; y[i]; i++) {\r
-               for (j = 0; y[i][j]; j++)\r
-                       printf(" %d", y[i][j]);\r
-               printf("\n");\r
-       }\r
-       f();\r
-       g(wordlist);\r
-       return 0;\r
-}\r
-\r
-f() {\r
-       static char *keywords[] = {"if", "for", "else", "while", 0, };\r
-       char **p;\r
-\r
-       for (p = keywords; *p; p++)\r
-               printf("%s\n", *p);\r
-}\r
-\r
-#ifdef NO_OLD_FUNC_DECL\r
-void g(Word *p)\r
-#else\r
-g(p)\r
-Word *p;\r
-#endif\r
-{\r
-       int i;\r
-\r
-       for ( ; p->codes[0]; p++) {\r
-               for (i = 0; i < sizeof p->codes/sizeof(p->codes[0]); i++)\r
-                       printf("%d ", p->codes[i]);\r
-               printf("%s\n", p->name);\r
-       }\r
-       h();\r
-}\r
-\r
-h()\r
-{\r
-       int i;\r
-\r
-       for (i = 0; i < sizeof(words)/sizeof(Word); i++)\r
-               printf("%d %d %d %s\n", words[i].codes[0],\r
-                       words[i].codes[1], words[i].codes[2],\r
-                       &words[i].name[0]);\r
-}\r
+/*
+  !!DESCRIPTION!! variable initialization
+  !!ORIGIN!!      LCC 4.1 Testsuite
+  !!LICENCE!!     own, freely distributeable for non-profit. read CPYRIGHT.LCC
+*/
+
+#include "common.h"
+/* todo: add back conditional stuff here ! */
+
+typedef struct { int codes[3]; char name[6]; } Word;
+
+#ifdef NO_IMPLICIT_FUNC_PROTOTYPES
+
+#ifdef NO_OLD_FUNC_DECL
+f();
+void g(Word *p);
+h();
+#else
+f();
+g();
+h();
+#endif
+
+#endif
+
+/*
+Word words[] = {
+        1, 2, 3,"if",
+       { { 4, 5 }, { 'f', 'o', 'r' } },
+        6, 7, 8, {"else"},
+        { { 9, 10, 11,}, 'w', 'h', 'i', 'l', 'e', },
+        { 0 },
+}, *wordlist = words;
+*/
+
+Word words[] = {
+        {{1, 2, 3},"if"},
+       { { 4, 5 }, { 'f', 'o', 'r' } },
+        {{6, 7, 8}, "else"},
+        { { 9, 10, 11}, {'w', 'h', 'i', 'l', 'e', }},
+        {{ 0 }},
+}, *wordlist = words;
+
+/*int x[][5] = { 1, 2, 3, 4, 0, { 5, 6 }, { 7 } };*/
+int x[][5] = { {1, 2, 3, 4, 0 }, { 5, 6 }, { 7 } };
+int *y[] = { x[0], x[1], x[2], 0 };
+
+main()
+{
+       int i, j;
+
+       for (i = 0; y[i]; i++) {
+               for (j = 0; y[i][j]; j++)
+                       printf(" %d", y[i][j]);
+               printf("\n");
+       }
+       f();
+       g(wordlist);
+       return 0;
+}
+
+f() {
+       static char *keywords[] = {"if", "for", "else", "while", 0, };
+       char **p;
+
+       for (p = keywords; *p; p++)
+               printf("%s\n", *p);
+}
+
+#ifdef NO_OLD_FUNC_DECL
+void g(Word *p)
+#else
+g(p)
+Word *p;
+#endif
+{
+       int i;
+
+       for ( ; p->codes[0]; p++) {
+               for (i = 0; i < sizeof p->codes/sizeof(p->codes[0]); i++)
+                       printf("%d ", p->codes[i]);
+               printf("%s\n", p->name);
+       }
+       h();
+}
+
+h()
+{
+       int i;
+
+       for (i = 0; i < sizeof(words)/sizeof(Word); i++)
+               printf("%d %d %d %s\n", words[i].codes[0],
+                       words[i].codes[1], words[i].codes[2],
+                       &words[i].name[0]);
+}
index d8c064ef3fbbfc36991fb4dbe36c3d6ef45273a0..29f9e3de40ac27327a646be5d5341bff02691f38 100644 (file)
-/*\r
-  !!DESCRIPTION!! pointer test\r
-  !!ORIGIN!!\r
-  !!LICENCE!!     public domain\r
-*/\r
-\r
-#include "common.h"\r
-#include <stdio.h>\r
-\r
-/*\r
-  check behaviour on incompletely declared arrays\r
-*/\r
-\r
-char i1[];\r
-\r
-void test1(void) {\r
-int a;\r
-\r
-       a=sizeof(i1[0]);\r
-       printf("%04x - ",a);\r
-       if(sizeof(i1[0])==sizeof(char)) {\r
-               /* gcc gives size of element */\r
-               printf("sizeof(i1[0]) gives size of element\n");\r
-       }\r
-       if(sizeof(i1[0])==sizeof(char*)) {\r
-               printf("sizeof(i1[0]) gives size of pointer to element\n");\r
-       }\r
-}\r
-\r
-/*\r
-  check behaviour on string init\r
-*/\r
-\r
-char t1[]="abcde";\r
-char t2[]={"abcde"};\r
-\r
-char *t3="abcde";\r
-char *t4={"abcde"};\r
-\r
-void test2(void) {\r
-char c1,c2,c3,c4;\r
-int i,e=0;\r
-       for(i=0;i<5;i++){\r
-               c1=t1[i];c2=t2[i];c3=t3[i];c4=t4[i];\r
-/*             printf("%02x %02x %02x %02x\n",c1,c2,c3,c4); */\r
-               printf("%c %c %c %c\n",c1,c2,c3,c4);\r
-               if(!((c1==c2)&(c1==c3)&(c1==c4))) e=1;\r
-       }\r
-       if(e) printf("test2 failed.\n");\r
-       else printf("test2 ok.\n");\r
-}\r
-\r
-/*\r
-  check behaviour on extern-declarations inside functions\r
-*/\r
-\r
-typedef struct {\r
-  char *name;\r
-  void *func;\r
-} A3;\r
-\r
-#ifdef NO_SLOPPY_STRUCT_INIT\r
-A3 a3[] = {\r
-  { "test3", (void*) NULL },\r
-  { "test3", (void*) NULL },\r
-};\r
-#else\r
-/*gcc warning: missing braces around initializer (near initialization for `a3[0]')\r
-  this type of struct-initialization seems to be kinda common */\r
-A3 a3[] = {\r
-    "test3", (void*) NULL  ,\r
-    "test3", (void*) NULL  ,\r
-};\r
-#endif\r
-\r
-void test3a(A3 *list, int number){\r
-       printf("%s %d\n",list->name,number);\r
-}\r
-\r
-static void test31(void)\r
-{\r
-    extern A3 a3[];\r
-    test3a(a3, -1);\r
-}\r
-\r
-#if 0\r
-/* this variation compiles and works with cc65, but gives an error with gcc :=P */\r
-static void test32(void)\r
-{\r
-    extern A3 *a3;\r
-    test3a(a3, -1);\r
-}\r
-#endif\r
-\r
-static void test30(void)\r
-{\r
-    test3a(a3, -1);\r
-}\r
-\r
-/*\r
-  todo: add test on function pointers in the form of (*func)(arg) ...\r
-  cc65 seems to have problems here aswell ;/\r
-*/\r
-\r
-int main(void) {\r
-       test1();\r
-       test2();\r
-       test30();\r
-       test31();\r
-/*     test32(); */\r
-       return 0;\r
-}\r
+/*
+  !!DESCRIPTION!! pointer test
+  !!ORIGIN!!
+  !!LICENCE!!     public domain
+*/
+
+#include "common.h"
+#include <stdio.h>
+
+/*
+  check behaviour on incompletely declared arrays
+*/
+
+char i1[];
+
+void test1(void) {
+int a;
+
+       a=sizeof(i1[0]);
+       printf("%04x - ",a);
+       if(sizeof(i1[0])==sizeof(char)) {
+               /* gcc gives size of element */
+               printf("sizeof(i1[0]) gives size of element\n");
+       }
+       if(sizeof(i1[0])==sizeof(char*)) {
+               printf("sizeof(i1[0]) gives size of pointer to element\n");
+       }
+}
+
+/*
+  check behaviour on string init
+*/
+
+char t1[]="abcde";
+char t2[]={"abcde"};
+
+char *t3="abcde";
+char *t4={"abcde"};
+
+void test2(void) {
+char c1,c2,c3,c4;
+int i,e=0;
+       for(i=0;i<5;i++){
+               c1=t1[i];c2=t2[i];c3=t3[i];c4=t4[i];
+/*             printf("%02x %02x %02x %02x\n",c1,c2,c3,c4); */
+               printf("%c %c %c %c\n",c1,c2,c3,c4);
+               if(!((c1==c2)&(c1==c3)&(c1==c4))) e=1;
+       }
+       if(e) printf("test2 failed.\n");
+       else printf("test2 ok.\n");
+}
+
+/*
+  check behaviour on extern-declarations inside functions
+*/
+
+typedef struct {
+  char *name;
+  void *func;
+} A3;
+
+#ifdef NO_SLOPPY_STRUCT_INIT
+A3 a3[] = {
+  { "test3", (void*) NULL },
+  { "test3", (void*) NULL },
+};
+#else
+/*gcc warning: missing braces around initializer (near initialization for `a3[0]')
+  this type of struct-initialization seems to be kinda common */
+A3 a3[] = {
+    "test3", (void*) NULL  ,
+    "test3", (void*) NULL  ,
+};
+#endif
+
+void test3a(A3 *list, int number){
+       printf("%s %d\n",list->name,number);
+}
+
+static void test31(void)
+{
+    extern A3 a3[];
+    test3a(a3, -1);
+}
+
+#if 0
+/* this variation compiles and works with cc65, but gives an error with gcc :=P */
+static void test32(void)
+{
+    extern A3 *a3;
+    test3a(a3, -1);
+}
+#endif
+
+static void test30(void)
+{
+    test3a(a3, -1);
+}
+
+/*
+  todo: add test on function pointers in the form of (*func)(arg) ...
+  cc65 seems to have problems here aswell ;/
+*/
+
+int main(void) {
+       test1();
+       test2();
+       test30();
+       test31();
+/*     test32(); */
+       return 0;
+}
index e75cfe71efa6c957c3fe7c3d2d71b7f4f65201a9..7a9bcecd7b820fc14807a324ef5427d5261d4519 100644 (file)
-/*\r
-  !!DESCRIPTION!! switch test\r
-  !!ORIGIN!!\r
-  !!LICENCE!!     public domain\r
-*/\r
-\r
-/*#define STANDALONE*/\r
-\r
-#include <stdio.h>\r
-\r
+/*
+  !!DESCRIPTION!! switch test
+  !!ORIGIN!!
+  !!LICENCE!!     public domain
+*/
+
+/*#define STANDALONE*/
+
+#include <stdio.h>
+
 void testlimits(int i) {
-       printf("%d:",i);\r
-\r
+       printf("%d:",i);
+
        switch(i) {
-               case -1:        /* works */\r
-               /* case 0xffff: */ /* 'range error' (-1) */\r
-\r
-                       printf("-1\n");\r
-                       break;\r
-               /* max int */\r
-\r
-/*              case 0x7fff:   */         /* works */\r
-               case 32767:                /* works */\r
-               /* case 32768: */          /* 'range error' (correct for that one!) */\r
-\r
-                       printf("max\n");\r
-                       break;\r
-               /* min int */\r
-\r
-               case -32768:               /* 'warning. constant is long' */\r
-               /* case 0x8000: */             /* 'range error' */\r
-               /* case -32769: */         /* 'range error' (correct for that one!) */\r
-                       printf("min\n");\r
-                       break;\r
-       }\r
-       printf("\n");\r
-}\r
-\r
-void testdefault1(unsigned char i) {\r
-/* we want a signed char */\r
-#ifdef REFCC\r
-\r
-#ifdef REFCC_UNSIGNED_CHARS\r
-signed char k;\r
-#else\r
-char k;\r
-#endif\r
-       \r
-#else\r
-       \r
-#ifdef UNSIGNED_CHARS\r
-signed char k;\r
-#else\r
-char k;\r
-#endif\r
-\r
-#endif\r
-\r
-       for(;i<254;) {\r
-               k = i;\r
-               printf(">%d\n",i);i++;\r
-               switch(k) {\r
-               case 1:\r
-                       break;\r
-               case 2:\r
-                       break;\r
-               case 3:\r
-                       break;\r
-               case 4:\r
-                       break;\r
-               case 5:\r
-                       break;\r
-               case 6:\r
-                       break;\r
-               case 7:\r
-                       break;\r
-               case 8:\r
-                       break;\r
-               case 9:\r
-                       break;\r
-               case 10:\r
-                       break;\r
-               case 11:\r
-                       break;\r
-               case 12:\r
-                       break;\r
-               case 13:\r
-                       break;\r
-               case 14:\r
-                       break;\r
-               case 15:\r
-                       break;\r
-               case 17:\r
-                       break;\r
-               /* triggers bug ? */\r
-               /* gcc warning: case label value exceeds maximum value for type */\r
-               /* cc65 error: range error */\r
-\r
-               /*\r
-               case 170:\r
-                       break;\r
-               */\r
-               case 18:\r
-                       break;\r
-               case 19:\r
-                       break;\r
-               case 20:\r
-                       break;\r
-               case 21:\r
-                       break;\r
-               case 22:\r
-                       break;\r
-               case 23:\r
-                       break;\r
-               case 24:\r
-                       switch(k) {\r
-                               case 1:\r
-                                       break;\r
-                               case 2:\r
-                                       break;\r
-                               case 3:\r
-                                       break;\r
-                               case 4:\r
-                               case 5:\r
-                               break;\r
-                               case 6:\r
-                               case 7:\r
-                                       break;\r
-                               case 8:\r
-                               case 9:\r
-                                       break;\r
-                               }\r
-                       break;\r
-               case 100:\r
-                       break;\r
-               default:\r
-                       printf(">>>default\n");\r
-                       /* triggers bug if this break; is missing? */\r
-                       /* break; */\r
-               }\r
-       }\r
-}\r
-\r
-void testdefault2(unsigned char i) {\r
-/* we want a unsigned char */\r
-#ifdef REFCC\r
-\r
-#ifdef REFCC_UNSIGNED_CHARS\r
-char k;\r
-#else\r
-unsigned char k;\r
-#endif\r
-       \r
-#else\r
-       \r
-#ifdef UNSIGNED_CHARS\r
-char k;\r
-#else\r
-unsigned char k;\r
-#endif\r
-\r
-#endif\r
-\r
-       for(;i<254;) {\r
-               k = i;\r
-               printf(">%d\n",i);i++;\r
-               switch(k) {\r
-               case 1:\r
-                       break;\r
-               case 2:\r
-                       break;\r
-               case 3:\r
-                       break;\r
-               case 4:\r
-                       break;\r
-               case 5:\r
-                       break;\r
-               case 6:\r
-                       break;\r
-               case 7:\r
-                       break;\r
-               case 8:\r
-                       break;\r
-               case 9:\r
-                       break;\r
-               case 10:\r
-                       break;\r
-               case 11:\r
-                       break;\r
-               case 12:\r
-                       break;\r
-               case 13:\r
-                       break;\r
-               case 14:\r
-                       break;\r
-               case 15:\r
-                       break;\r
-               case 17:\r
-                       break;\r
-               /* triggers bug ? */\r
-\r
-               case 170:\r
-                       break;\r
-               \r
-               case 18:\r
-                       break;\r
-               case 19:\r
-                       break;\r
-               case 20:\r
-                       break;\r
-               case 21:\r
-                       break;\r
-               case 22:\r
-                       break;\r
-               case 23:\r
-                       break;\r
-               case 24:\r
-                       switch(k) {\r
-                               case 1:\r
-                                       break;\r
-                               case 2:\r
-                                       break;\r
-                               case 3:\r
-                                       break;\r
-                               case 4:\r
-                               case 5:\r
-                               break;\r
-                               case 6:\r
-                               case 7:\r
-                                       break;\r
-                               case 8:\r
-                               case 9:\r
-                                       break;\r
-                               }\r
-                       break;\r
-               case 100:\r
-                       break;\r
-               default:\r
-                       printf(">>>default\n");\r
-                       /* triggers bug if this break; is missing? */\r
-                       /* break; */\r
-               }\r
-       }\r
+               case -1:        /* works */
+               /* case 0xffff: */ /* 'range error' (-1) */
+
+                       printf("-1\n");
+                       break;
+               /* max int */
+
+/*              case 0x7fff:   */         /* works */
+               case 32767:                /* works */
+               /* case 32768: */          /* 'range error' (correct for that one!) */
+
+                       printf("max\n");
+                       break;
+               /* min int */
+
+               case -32768:               /* 'warning. constant is long' */
+               /* case 0x8000: */             /* 'range error' */
+               /* case -32769: */         /* 'range error' (correct for that one!) */
+                       printf("min\n");
+                       break;
+       }
+       printf("\n");
+}
+
+void testdefault1(unsigned char i) {
+/* we want a signed char */
+#ifdef REFCC
+
+#ifdef REFCC_UNSIGNED_CHARS
+signed char k;
+#else
+char k;
+#endif
+       
+#else
+       
+#ifdef UNSIGNED_CHARS
+signed char k;
+#else
+char k;
+#endif
+
+#endif
+
+       for(;i<254;) {
+               k = i;
+               printf(">%d\n",i);i++;
+               switch(k) {
+               case 1:
+                       break;
+               case 2:
+                       break;
+               case 3:
+                       break;
+               case 4:
+                       break;
+               case 5:
+                       break;
+               case 6:
+                       break;
+               case 7:
+                       break;
+               case 8:
+                       break;
+               case 9:
+                       break;
+               case 10:
+                       break;
+               case 11:
+                       break;
+               case 12:
+                       break;
+               case 13:
+                       break;
+               case 14:
+                       break;
+               case 15:
+                       break;
+               case 17:
+                       break;
+               /* triggers bug ? */
+               /* gcc warning: case label value exceeds maximum value for type */
+               /* cc65 error: range error */
+
+               /*
+               case 170:
+                       break;
+               */
+               case 18:
+                       break;
+               case 19:
+                       break;
+               case 20:
+                       break;
+               case 21:
+                       break;
+               case 22:
+                       break;
+               case 23:
+                       break;
+               case 24:
+                       switch(k) {
+                               case 1:
+                                       break;
+                               case 2:
+                                       break;
+                               case 3:
+                                       break;
+                               case 4:
+                               case 5:
+                               break;
+                               case 6:
+                               case 7:
+                                       break;
+                               case 8:
+                               case 9:
+                                       break;
+                               }
+                       break;
+               case 100:
+                       break;
+               default:
+                       printf(">>>default\n");
+                       /* triggers bug if this break; is missing? */
+                       /* break; */
+               }
+       }
+}
+
+void testdefault2(unsigned char i) {
+/* we want a unsigned char */
+#ifdef REFCC
+
+#ifdef REFCC_UNSIGNED_CHARS
+char k;
+#else
+unsigned char k;
+#endif
+       
+#else
+       
+#ifdef UNSIGNED_CHARS
+char k;
+#else
+unsigned char k;
+#endif
+
+#endif
+
+       for(;i<254;) {
+               k = i;
+               printf(">%d\n",i);i++;
+               switch(k) {
+               case 1:
+                       break;
+               case 2:
+                       break;
+               case 3:
+                       break;
+               case 4:
+                       break;
+               case 5:
+                       break;
+               case 6:
+                       break;
+               case 7:
+                       break;
+               case 8:
+                       break;
+               case 9:
+                       break;
+               case 10:
+                       break;
+               case 11:
+                       break;
+               case 12:
+                       break;
+               case 13:
+                       break;
+               case 14:
+                       break;
+               case 15:
+                       break;
+               case 17:
+                       break;
+               /* triggers bug ? */
+
+               case 170:
+                       break;
+               
+               case 18:
+                       break;
+               case 19:
+                       break;
+               case 20:
+                       break;
+               case 21:
+                       break;
+               case 22:
+                       break;
+               case 23:
+                       break;
+               case 24:
+                       switch(k) {
+                               case 1:
+                                       break;
+                               case 2:
+                                       break;
+                               case 3:
+                                       break;
+                               case 4:
+                               case 5:
+                               break;
+                               case 6:
+                               case 7:
+                                       break;
+                               case 8:
+                               case 9:
+                                       break;
+                               }
+                       break;
+               case 100:
+                       break;
+               default:
+                       printf(">>>default\n");
+                       /* triggers bug if this break; is missing? */
+                       /* break; */
+               }
+       }
 }
 
 int main(void) {
-       testlimits(32767);\r
-       testlimits(-32768);\r
-       testlimits(-1);\r
-       \r
-       testdefault1(1);\r
-       testdefault1(2);\r
-       testdefault1(3);\r
-       testdefault1(4);\r
-       \r
-       testdefault2(1);\r
-       testdefault2(2);\r
-       testdefault2(3);\r
-       testdefault2(4);\r
-\r
-       return 0;\r
-}\r
+       testlimits(32767);
+       testlimits(-32768);
+       testlimits(-1);
+       
+       testdefault1(1);
+       testdefault1(2);
+       testdefault1(3);
+       testdefault1(4);
+       
+       testdefault2(1);
+       testdefault2(2);
+       testdefault2(3);
+       testdefault2(4);
+
+       return 0;
+}
index 11fd33b3829c615b41da580fa1bf2a5640b1f66d..3d61fdbd0d5b6bcf4fca13696625cdf078066b79 100644 (file)
 /*
-  !!DESCRIPTION!! varargs test\r
-  !!ORIGIN!!\r
-  !!LICENCE!!     public domain\r
-*/\r
-\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <stdarg.h>\r
-\r
-void chk0(char *format,...);\r
-void chk1(int fd,char *format,...);\r
-\r
-#if 0\r
-// old workaround for broken varargs\r
-\r
-void chk0(char *format,...){\r
-    __asm__ ("pha");    // save argument size\r
-    {\r
-//va_list ap;\r
-char *ap;\r
-char *_format;\r
-static char string[0x100];\r
-\r
-//    va_start(ap,format);\r
-    __asm__ ("pla");       // restore argument size\r
-    __asm__ ("ldx #$00");  // clear hibyte of AX\r
-    ap=__AX__;\r
-    ap+=(char*)&format;\r
-    // get value of format\r
-    ap-=2;\r
-    _format=*((char**)ap);\r
-\r
-//    vsprintf(string,format,ap);\r
-    vsprintf(&string[0],_format,ap);\r
-    printf("format:%s,string:%s\n",_format,string);\r
-//    va_end(ap);\r
-\r
-    }\r
-}\r
-\r
-void chk1(int fd,char *format,...){\r
-    __asm__ ("pha");    // save argument size\r
-    {\r
-//va_list ap;\r
-char *ap;\r
-char *_format;\r
-int _fd;\r
-static char string[0x100];\r
-\r
-//    va_start(ap,format);\r
-    __asm__ ("pla");       // restore argument size\r
-    __asm__ ("ldx #$00");  // clear hibyte of AX\r
-    ap=__AX__;\r
-    ap+=(char*)&format;\r
-    // get value of fd\r
-    ap-=2;\r
-    _fd=*((int*)ap);\r
-    // get value of format\r
-    ap-=2;\r
-    _format=*((char**)ap);\r
-\r
-//    vsprintf(string,format,ap);\r
-    vsprintf(&string[0],_format,ap);\r
-    printf("fd:%d,format:%s,string:%s\n",_fd,_format,string);\r
-//    va_end(ap);\r
-\r
-    }\r
-}\r
-\r
-#endif\r
-\r
-void chk0(char *format,...){\r
-va_list ap;\r
-static char string[0x100];\r
-    va_start(ap,format);\r
-    vsprintf(string,format,ap);\r
-    printf("format:%s,string:%s\n",format,string);\r
-    va_end(ap);\r
-}\r
-\r
-void chk1(int fd,char *format,...){\r
-va_list ap;\r
-static char string[0x100];\r
-\r
-    va_start(ap,format);\r
-\r
-    vsprintf(string,format,ap);\r
-       printf("fd:%d,format:%s,string:%s\n",fd,format,string);\r
-    va_end(ap);\r
+  !!DESCRIPTION!! varargs test
+  !!ORIGIN!!
+  !!LICENCE!!     public domain
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+void chk0(char *format,...);
+void chk1(int fd,char *format,...);
+
+#if 0
+// old workaround for broken varargs
+
+void chk0(char *format,...){
+    __asm__ ("pha");    // save argument size
+    {
+//va_list ap;
+char *ap;
+char *_format;
+static char string[0x100];
+
+//    va_start(ap,format);
+    __asm__ ("pla");       // restore argument size
+    __asm__ ("ldx #$00");  // clear hibyte of AX
+    ap=__AX__;
+    ap+=(char*)&format;
+    // get value of format
+    ap-=2;
+    _format=*((char**)ap);
+
+//    vsprintf(string,format,ap);
+    vsprintf(&string[0],_format,ap);
+    printf("format:%s,string:%s\n",_format,string);
+//    va_end(ap);
+
+    }
+}
+
+void chk1(int fd,char *format,...){
+    __asm__ ("pha");    // save argument size
+    {
+//va_list ap;
+char *ap;
+char *_format;
+int _fd;
+static char string[0x100];
+
+//    va_start(ap,format);
+    __asm__ ("pla");       // restore argument size
+    __asm__ ("ldx #$00");  // clear hibyte of AX
+    ap=__AX__;
+    ap+=(char*)&format;
+    // get value of fd
+    ap-=2;
+    _fd=*((int*)ap);
+    // get value of format
+    ap-=2;
+    _format=*((char**)ap);
+
+//    vsprintf(string,format,ap);
+    vsprintf(&string[0],_format,ap);
+    printf("fd:%d,format:%s,string:%s\n",_fd,_format,string);
+//    va_end(ap);
+
+    }
 }
 
-int main(int argc,char **argv) {\r
-    printf("varargs test\n");\r
-\r
-    printf("\nchk0/0:\n");chk0("chk0 %s","arg0");\r
-    printf("\nchk0/1:\n");chk0("chk0 %s %s","arg0","arg1");\r
-    printf("\nchk0/2:\n");chk0("chk0 %s %s %s","arg0","arg1","arg2");\r
-\r
-    printf("\nchk1/0:\n");chk1(0xfd,"chk1 %s","arg0");\r
-    printf("\nchk1/1:\n");chk1(0xfd,"chk1 %s %s","arg0","arg1");\r
-    printf("\nchk1/2:\n");chk1(0xfd,"chk1 %s %s %s","arg0","arg1","arg2");\r
-\r
+#endif
+
+void chk0(char *format,...){
+va_list ap;
+static char string[0x100];
+    va_start(ap,format);
+    vsprintf(string,format,ap);
+    printf("format:%s,string:%s\n",format,string);
+    va_end(ap);
+}
+
+void chk1(int fd,char *format,...){
+va_list ap;
+static char string[0x100];
+
+    va_start(ap,format);
+
+    vsprintf(string,format,ap);
+       printf("fd:%d,format:%s,string:%s\n",fd,format,string);
+    va_end(ap);
+}
+
+int main(int argc,char **argv) {
+    printf("varargs test\n");
+
+    printf("\nchk0/0:\n");chk0("chk0 %s","arg0");
+    printf("\nchk0/1:\n");chk0("chk0 %s %s","arg0","arg1");
+    printf("\nchk0/2:\n");chk0("chk0 %s %s %s","arg0","arg1","arg2");
+
+    printf("\nchk1/0:\n");chk1(0xfd,"chk1 %s","arg0");
+    printf("\nchk1/1:\n");chk1(0xfd,"chk1 %s %s","arg0","arg1");
+    printf("\nchk1/2:\n");chk1(0xfd,"chk1 %s %s %s","arg0","arg1","arg2");
+
     return 0;
-}\r
+}
index 5768f80d00b5fb5708c8db6aa58018ecb0e68882..ab72e24c0881e48868e4d35c6160464b6ae7e3d0 100644 (file)
@@ -562,13 +562,13 @@ yylook()
                }
 
 # ifdef LEXDEBUG
-               if((*(lsp-1)-yysvec-1)<0)
+               if (lsp == yylstate)
                {
                        fprintf(yyout,"yylook:  stopped (end)\n");
                }
                else
                {
-                       fprintf(yyout,"yylook:  stopped at %d with\n",*(lsp-1)-yysvec-1);
+                       fprintf(yyout,"yylook:  stopped at %d with:\n",*(lsp-1)-(yysvec+1));
                }
 # endif
                while (lsp-- > yylstate)
@@ -594,7 +594,7 @@ yylook()
                                yyleng = yylastch-yytext+1;
                                yytext[yyleng] = 0;
 # ifdef LEXDEBUG
-                               fprintf(yyout,"\nyylook:  match action %d\n",*yyfnd);
+                               fprintf(yyout,"yylook:  match action %d\n",*yyfnd);
                                fprintf(yyout,"yylook:  done loops: %d\n",testbreak);
 # endif
                                return(*yyfnd++);
diff --git a/test/val/static-fwd-decl.c b/test/val/static-fwd-decl.c
new file mode 100644 (file)
index 0000000..420640d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+  !!DESCRIPTION!! static forward declarations
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Bob Andrews
+*/
+
+/*
+  see: https://github.com/cc65/cc65/issues/204
+*/
+
+#pragma warn(error, on)
+
+typedef struct _DIRMENU
+{
+    const char *name;
+    struct _DIRMENU *dest;
+} DIRMENU; 
+
+static DIRMENU rmenu;
+
+static DIRMENU lmenu = {
+    "left",
+    &rmenu
+};
+
+static DIRMENU rmenu = {
+    "right",
+    &lmenu
+};
+
+int main(void)
+{
+    return lmenu.dest == &rmenu && rmenu.dest == &lmenu ? 0 : 1;
+}
diff --git a/test/val/void-size1.c b/test/val/void-size1.c
new file mode 100644 (file)
index 0000000..0c2dcca
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+  !!DESCRIPTION!! Getting the size of a void-type variable (cc65 extension)
+  !!ORIGIN!!      cc65 regression tests
+  !!LICENCE!!     Public Domain
+  !!AUTHOR!!      Greg King
+*/
+
+static const void list1 = {
+    (char)1,
+    (char)2,
+    (char)3,
+    (char)4,
+    (char)5,
+    (char)6,
+    (char)7,
+    (char)8,
+    (char)9,
+    (char)0
+};
+
+static void list2 = {
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    0
+};
+
+void list3 = {
+    (char)1,
+    (char)2,
+    (char)3,
+    (char)4,
+    &list1,
+    (char)6,
+    (char)7,
+    (char)8,
+    (char)9,
+    &list2
+};
+
+/* We know that the expression is constant; don't tell us. */
+
+#pragma warn (const-comparison, off)
+
+int main (void)
+{
+    return sizeof list1 != 10
+        || sizeof list2 != 20
+        || sizeof list3 != 12;
+}
index 04c5998786eb1cddb1b1c5f4c56af9ab5b82afd3..ae1931e64df042ede5534102349a44ed596a98a4 100644 (file)
@@ -1,59 +1,55 @@
 /*
-** testprogram for ANTIC instructions as defined in "_antic.h"
+** test program for ANTIC instructions as defined in "_antic.h"
 **
 ** 23-Feb-2017, Christian Krueger
 */
 
 #include <conio.h>
 #include <atari.h>
-#include <peekpoke.h>
-#include <string.h>
 
-// code is only for testing purposes, as screen and display list are not aligned
+// code is only for testing purposes, as screen and display list are not aligned,
 // and jumps not set!
 
 unsigned char DummyScreen[400];
 
 void DisplayList = {
-       DL_BLK1,
-       DL_BLK2,
-       DL_BLK3,
-       DL_BLK4,
-       DL_BLK5,
-       DL_BLK6,
-       DL_BLK7,
-       DL_DLI(DL_BLK8),
-       DL_LMS(DL_CHR40x8x1),
-       DummyScreen,
-       DL_HSCROL(DL_CHR40x10x1),
-       DL_VSCROL(DL_CHR40x8x4),
-       DL_CHR40x16x4,
-       DL_LMS(DL_HSCROL(DL_VSCROL(DL_DLI(DL_CHR20x8x2)))),
-       DummyScreen+120,
-       DL_CHR20x16x2,
-       DL_MAP40x8x4,
-       DL_MAP80x4x2,
-       DL_MAP80x4x4,
-       DL_MAP160x2x2,
-       DL_MAP160x1x2,
-       DL_MAP160x2x4,
-       DL_MAP160x1x4,
-       DL_MAP320x1x1, 
-       DL_JVB,
-       DL_JMP
+    DL_BLK1,
+    DL_BLK2,
+    DL_BLK3,
+    DL_BLK4,
+    DL_BLK5,
+    DL_BLK6,
+    DL_BLK7,
+    DL_DLI(DL_BLK8),
+    DL_LMS(DL_CHR40x8x1),
+    DummyScreen,
+    DL_HSCROL(DL_CHR40x10x1),
+    DL_VSCROL(DL_CHR40x8x4),
+    DL_CHR40x16x4,
+    DL_LMS(DL_HSCROL(DL_VSCROL(DL_DLI(DL_CHR20x8x2)))),
+    DummyScreen+120,
+    DL_CHR20x16x2,
+    DL_MAP40x8x4,
+    DL_MAP80x4x2,
+    DL_MAP80x4x4,
+    DL_MAP160x2x2,
+    DL_MAP160x1x2,
+    DL_MAP160x2x4,
+    DL_MAP160x1x4,
+    DL_MAP320x1x1,
+    DL_JVB,
+    DL_JMP
 };
 
-unsigned char dlend = 0;
 
+/* We know that the sizeof expression is constant; don't tell us. */
+
+#pragma warn (const-comparison, off)
 
 int
 main(void)
 {
-    // unfortunately "sizeof()" doesn't work with void data
-    // (Error: Size of data type is unknown)
-    // so we trick with the addresses at front and end...
-
-    int returnValue = (((unsigned int)&dlend-(unsigned int)&DisplayList) != 28);  // assure only one byte per instruction!
+    int returnValue = (sizeof DisplayList != 28);       // assure only one byte per instruction!
 
     clrscr();
     if (returnValue)
@@ -66,4 +62,3 @@ main(void)
 
     return returnValue;
 }
-
index 2daf5aa062f03928eca6789225557aabe7685e82..f9db3f641a8f19a8fed601e1e8376dbbb29c521a 100644 (file)
-/* mul-test.c -- Test the multiplication operator. */\r
-\r
-#include <time.h>\r
-#include <conio.h>\r
-#include <ctype.h>\r
-\r
-\r
-/* Number of elements in the progress bar. Use a power of 2, to avoid the\r
-** multiplication (which is about to be tested).\r
-*/\r
-#define BAR_ELEMENTS    32U\r
-\r
-#if defined(__CBM__)\r
-static const unsigned char revers_bar[8] = {\r
-    0, 0, 0, 0, 0, 1, 1, 1\r
-};\r
-static const unsigned char small_bar[8] = {\r
-    ' ', 0xa5, 0xb4, 0xb5, 0xa1, 0xb6, 0xaa, 0xa7\r
-};\r
-\r
-#elif defined(__ATARI__)\r
-#endif\r
-\r
-/* Screen co-ordinates for the progress meter */\r
-static unsigned char Width, Height;\r
-static unsigned char X, Y;\r
-\r
-static void ProgressMeter (unsigned Val)\r
-/* Print the progress bar. */\r
-{\r
-    gotoxy (X, Y);\r
-    cprintf (" %5lu/65536\r\n", (unsigned long) Val);\r
-    revers (1);\r
-    cclear (Val / (unsigned)(65536U / BAR_ELEMENTS));\r
-\r
-/* Commodore and Atari computers can show eight times greater precision. */\r
-#if defined(__CBM__)\r
-    Val = (Val / (unsigned)(65536U / BAR_ELEMENTS / 8)) % 8;\r
-    revers (revers_bar[Val]);\r
-    cputc (small_bar[Val]);\r
-\r
-#elif defined(__ATARI__)\r
-#endif\r
-\r
-    revers (0);\r
-}\r
-\r
-\r
-\r
-int main(void)\r
-{\r
-    char C;\r
-\r
-    /* Clock variables */\r
-    clock_t Ticks;\r
-    clock_t Wait;\r
-    unsigned Days;\r
-    unsigned Hours;\r
-    unsigned Minu;\r
-    unsigned Sec;\r
-    unsigned Milli;\r
-\r
-    /* Actual test variables */\r
-    register unsigned lhs = 0;\r
-    register unsigned rhs = 0;\r
-    register unsigned res;\r
-\r
-    /* Clear the screen, and output an informational message. */\r
-    clrscr ();\r
-    screensize (&Width, &Height);\r
-    cprintf ("This program does an exhaustive test of\r\n"\r
-             "the multiplication routine. It runs for\r\n"\r
-             "several days; so, please wait very\r\n"\r
-             "patiently (or, speed up your emulator).\r\n"\r
-             "\n"\r
-             "Progress: ");\r
-\r
-    /* Remember the current position for the progress bar */\r
-    X = wherex ();\r
-    Y = wherey ();\r
-\r
-    /* Mark the maximum limit of the bar. */\r
-    revers (1);\r
-    cputcxy (BAR_ELEMENTS, Y, ' ');\r
-    cputcxy (BAR_ELEMENTS, Y + 1, ' ');\r
-    revers (0);\r
-\r
-/* [Targets that have clock() will define CLOCKS_PER_SEC.] */\r
-#ifdef CLOCKS_PER_SEC\r
-\r
-    /* Start timing the test. */\r
-    Ticks = clock();\r
-#endif\r
-\r
-    do {\r
-\r
-        /* Update the progress bar */\r
-        ProgressMeter (lhs);\r
-\r
-/* Enable this to test the progress-meter code.\r
-** (And, run emulators at their maximun speed.)\r
-*/\r
-#if 0\r
-        continue;\r
-#endif\r
-\r
-        /* Do one row of tests */\r
-        res = 0;\r
-        do {\r
-            if (lhs * rhs != res) {\r
-#ifdef CLOCKS_PER_SEC\r
-                Wait = clock ();\r
-#endif\r
-                gotoxy (0, Y+3);\r
-                cprintf ("Error on %u * %u: %u != %u\r\n", lhs, rhs, lhs * rhs, res);\r
-                cprintf ("Press a key -- 'Q' to quit. ");\r
-                cursor (1);\r
-                C = toupper (cgetc ());\r
-                cclearxy (0, Y+3, Width);\r
-                cclearxy (0, Y+4, Width);\r
-\r
-#ifdef CLOCKS_PER_SEC\r
-\r
-                /* Don't time the user's interaction. */\r
-                Ticks += clock () - Wait;\r
-#endif\r
-\r
-                if (C == 'Q') {\r
-                    goto Done;\r
-                }\r
-            }\r
-\r
-            if (kbhit () && toupper (cgetc ()) == 'Q') {\r
-                goto Done;\r
-            }\r
-\r
-            res += lhs;\r
-        } while (++rhs != 0);\r
-\r
-    } while (++lhs != 0);\r
-\r
-Done:\r
-#ifdef CLOCKS_PER_SEC\r
-\r
-    /* Calculate the time used */\r
-    Ticks = clock() - Ticks;\r
-    Milli = ((Ticks % CLOCKS_PER_SEC) * 1000) / CLOCKS_PER_SEC;\r
-    Sec = (unsigned) (Ticks / CLOCKS_PER_SEC);\r
-    Minu = Sec / 60;\r
-    Hours = Minu / 60;\r
-    Days = Hours / 24;\r
-    Hours %= 24;\r
-    Minu %= 60;\r
-    Sec %= 60;\r
-\r
-    /* Print the time used */\r
-    gotoxy (0, Y+3);\r
-    cprintf ("Time used:\r\n"\r
-             " %u days,\r\n"\r
-             " %u hours,\r\n"\r
-             " %u minutes,\r\n"\r
-             " %u.%03u seconds.\n", Days, Hours, Minu, Sec, Milli);\r
-#endif\r
-\r
-    cprintf ("\rTap a key, to exit. ");\r
-    cgetc();\r
-    return 0;\r
-}\r
-\r
-\r
+/* mul-test.c -- Test the multiplication operator. */
+
+#include <time.h>
+#include <conio.h>
+#include <ctype.h>
+
+
+/* Number of elements in the progress bar. Use a power of 2, to avoid the
+** multiplication (which is about to be tested).
+*/
+#define BAR_ELEMENTS    32U
+
+#if defined(__CBM__)
+static const unsigned char revers_bar[8] = {
+    0, 0, 0, 0, 0, 1, 1, 1
+};
+static const unsigned char small_bar[8] = {
+    ' ', 0xa5, 0xb4, 0xb5, 0xa1, 0xb6, 0xaa, 0xa7
+};
+
+#elif defined(__ATARI__)
+#endif
+
+/* Screen co-ordinates for the progress meter */
+static unsigned char Width, Height;
+static unsigned char X, Y;
+
+static void ProgressMeter (unsigned Val)
+/* Print the progress bar. */
+{
+    gotoxy (X, Y);
+    cprintf (" %5lu/65536\r\n", (unsigned long) Val);
+    revers (1);
+    cclear (Val / (unsigned)(65536U / BAR_ELEMENTS));
+
+/* Commodore and Atari computers can show eight times greater precision. */
+#if defined(__CBM__)
+    Val = (Val / (unsigned)(65536U / BAR_ELEMENTS / 8)) % 8;
+    revers (revers_bar[Val]);
+    cputc (small_bar[Val]);
+
+#elif defined(__ATARI__)
+#endif
+
+    revers (0);
+}
+
+
+
+int main(void)
+{
+    char C;
+
+    /* Clock variables */
+    clock_t Ticks;
+    clock_t Wait;
+    unsigned Days;
+    unsigned Hours;
+    unsigned Minu;
+    unsigned Sec;
+    unsigned Milli;
+
+    /* Actual test variables */
+    register unsigned lhs = 0;
+    register unsigned rhs = 0;
+    register unsigned res;
+
+    /* Clear the screen, and output an informational message. */
+    clrscr ();
+    screensize (&Width, &Height);
+    cprintf ("This program does an exhaustive test of\r\n"
+             "the multiplication routine. It runs for\r\n"
+             "several days; so, please wait very\r\n"
+             "patiently (or, speed up your emulator).\r\n"
+             "\n"
+             "Progress: ");
+
+    /* Remember the current position for the progress bar */
+    X = wherex ();
+    Y = wherey ();
+
+    /* Mark the maximum limit of the bar. */
+    revers (1);
+    cputcxy (BAR_ELEMENTS, Y, ' ');
+    cputcxy (BAR_ELEMENTS, Y + 1, ' ');
+    revers (0);
+
+/* [Targets that have clock() will define CLOCKS_PER_SEC.] */
+#ifdef CLOCKS_PER_SEC
+
+    /* Start timing the test. */
+    Ticks = clock();
+#endif
+
+    do {
+
+        /* Update the progress bar */
+        ProgressMeter (lhs);
+
+/* Enable this to test the progress-meter code.
+** (And, run emulators at their maximun speed.)
+*/
+#if 0
+        continue;
+#endif
+
+        /* Do one row of tests */
+        res = 0;
+        do {
+            if (lhs * rhs != res) {
+#ifdef CLOCKS_PER_SEC
+                Wait = clock ();
+#endif
+                gotoxy (0, Y+3);
+                cprintf ("Error on %u * %u: %u != %u\r\n", lhs, rhs, lhs * rhs, res);
+                cprintf ("Press a key -- 'Q' to quit. ");
+                cursor (1);
+                C = toupper (cgetc ());
+                cclearxy (0, Y+3, Width);
+                cclearxy (0, Y+4, Width);
+
+#ifdef CLOCKS_PER_SEC
+
+                /* Don't time the user's interaction. */
+                Ticks += clock () - Wait;
+#endif
+
+                if (C == 'Q') {
+                    goto Done;
+                }
+            }
+
+            if (kbhit () && toupper (cgetc ()) == 'Q') {
+                goto Done;
+            }
+
+            res += lhs;
+        } while (++rhs != 0);
+
+    } while (++lhs != 0);
+
+Done:
+#ifdef CLOCKS_PER_SEC
+
+    /* Calculate the time used */
+    Ticks = clock() - Ticks;
+    Milli = ((Ticks % CLOCKS_PER_SEC) * 1000) / CLOCKS_PER_SEC;
+    Sec = (unsigned) (Ticks / CLOCKS_PER_SEC);
+    Minu = Sec / 60;
+    Hours = Minu / 60;
+    Days = Hours / 24;
+    Hours %= 24;
+    Minu %= 60;
+    Sec %= 60;
+
+    /* Print the time used */
+    gotoxy (0, Y+3);
+    cprintf ("Time used:\r\n"
+             " %u days,\r\n"
+             " %u hours,\r\n"
+             " %u minutes,\r\n"
+             " %u.%03u seconds.\n", Days, Hours, Minu, Sec, Milli);
+#endif
+
+    cprintf ("\rTap a key, to exit. ");
+    cgetc();
+    return 0;
+}
+
+