diff --git a/.travis.yml b/.travis.yml index a11412230..10ea789cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,12 @@ language: - c install: + - sudo apt-get update - sudo apt-get install linuxdoc-tools linuxdoc-tools-info binutils-mingw-w64-i686 gcc-mingw-w64-i686 sshpass script: - make bin USER_CFLAGS=-Werror - make lib QUIET=1 + - make -C test - make -C src clean - make bin USER_CFLAGS=-Werror CROSS_COMPILE=i686-w64-mingw32- - make doc zip diff --git a/LICENSE b/LICENSE index 03eefac67..88cacf148 100644 --- a/LICENSE +++ b/LICENSE @@ -1,44 +1,3 @@ -This is the original cc65 compiler copyright: - - -*- Mode: Text -*- - - This is the copyright notice for RA65, LINK65, LIBR65, and other - Atari 8-bit programs. Said programs are Copyright 1989, by John R. - Dunning. All rights reserved, with the following exceptions: - - Anyone may copy or redistribute these programs, provided that: - - 1: You don't charge anything for the copy. It is permissable to - charge a nominal fee for media, etc. - - 2: All source code and documentation for the programs is made - available as part of the distribution. - - 3: This copyright notice is preserved verbatim, and included in - the distribution. - - You are allowed to modify these programs, and redistribute the - modified versions, provided that the modifications are clearly noted. - - There is NO WARRANTY with this software, it comes as is, and is - distributed in the hope that it may be useful. - - This copyright notice applies to any program which contains - this text, or the refers to this file. - - This copyright notice is based on the one published by the Free - Software Foundation, sometimes known as the GNU project. The idea - is the same as theirs, ie the software is free, and is intended to - stay that way. Everybody has the right to copy, modify, and re- - distribute this software. Nobody has the right to prevent anyone - else from copying, modifying or redistributing it. - -In acknowledgment of this copyright, I (Ullrich von Bassewitz) will place -my own changes to the compiler under the same copyright. - -The library and the binary utils are a complete rewrite done by me and -covered by the following license: - This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. diff --git a/Makefile.travis b/Makefile.travis index 78ded63e6..4c0f688f8 100644 --- a/Makefile.travis +++ b/Makefile.travis @@ -24,7 +24,7 @@ endif SF_USER = oliverschmidt SF_HOST = frs.sourceforge.net -SF_FILE = /home/frs/project/cc65/cc65-snapshot-win64.zip +SF_FILE = /home/frs/project/cc65/cc65-snapshot-win32.zip SCPFLAGS = -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -q diff --git a/README.md b/README.md index bf7d6dcde..a0455cbe6 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -[documentation](http://cc65.github.io/doc) +[Windows Snapshot](http://sourceforge.net/projects/cc65/files/cc65-snapshot-win32.zip) -[wiki](http://github.com/cc65/wiki/wiki) +[Documentation](http://cc65.github.io/doc) -[![build status](http://travis-ci.org/cc65/cc65.png)](http://travis-ci.org/cc65/cc65/builds) +[Wiki](http://github.com/cc65/wiki/wiki) + +[![Build Status](https://api.travis-ci.org/cc65/cc65.svg?branch=master)](https://travis-ci.org/cc65/cc65/builds) cc65 is a complete cross development package for 65(C)02 systems, including a powerful macro assembler, a C compiler, linker, librarian and several @@ -19,14 +21,16 @@ including - CBM 510 (aka P500) - the 600/700 family - newer PET machines (not 2001). -- the Apple ][+ and successors. +- the Apple ]\[+ and successors. - the Atari 8 bit machines. - the Atari 5200 console. - GEOS for the C64, C128 and Apple //e. +- the NEC PC-Engine (aka TurboGrafx-16). - the Nintendo Entertainment System (NES) console. -- the Supervision console. +- the Watara Supervision console. - the Oric Atmos. - the Lynx console. +- the Ohio Scientific Challenger 1P. The libraries are fairly portable, so creating a version for other 6502s shouldn't be too much work. diff --git a/asminc/c64.inc b/asminc/c64.inc index f450fcc0b..ababb1ea0 100644 --- a/asminc/c64.inc +++ b/asminc/c64.inc @@ -6,6 +6,8 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +VARTAB := $2D ; Pointer to start of BASIC variables +MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1) TXTPTR := $7A ; Pointer into BASIC source code TIME := $A0 ; 60 HZ clock FNAM_LEN := $B7 ; Length of filename @@ -22,6 +24,7 @@ SCREEN_PTR := $D1 ; Pointer to current char in text screen CURS_X := $D3 ; Cursor column CURS_Y := $D6 ; Cursor row CRAM_PTR := $F3 ; Pointer to current char in color RAM +FREKZP := $FB ; Five unused bytes BASIC_BUF := $200 ; Location of command-line BASIC_BUF_LEN = 89 ; Maximum length of command-line @@ -210,4 +213,3 @@ CASSMOT = $20 ; Cassette motor on TP_FAST = $80 ; Switch Rossmoeller TurboProcess to fast mode RAMONLY = $F8 ; (~(LORAM | HIRAM | IOEN)) & $FF - diff --git a/asminc/pce.inc b/asminc/pce.inc new file mode 100644 index 000000000..623ab4da8 --- /dev/null +++ b/asminc/pce.inc @@ -0,0 +1,92 @@ +; +; PCE definitions. By Groepaz/Hitmem. +; + +; FIXME: screen dimensions my change according to selected video mode +screenrows = (224/8) +charsperline = 61 + +CH_HLINE = 1 +CH_VLINE = 2 + +; huc6270 - Video Display Controller (VDC) + +VDC_MAWR = 0 ; Memory Address Write Register +VDC_MARR = 1 ; Memory Address Read Register +VDC_VWR = 2 ; VRAM Write Register (write only) +VDC_VRR = 2 ; VRAM Read Register (read only) +VDC_UNK03 = 3 ; (unknown) +VDC_UNK04 = 4 ; (unknown) +VDC_CR = 5 ; Control Register +VDC_RCR = 6 ; Raster Counter Register +VDC_BXR = 7 ; Background X-Scroll Register +VDC_BYR = 8 ; Background Y-Scroll Register +VDC_MWR = 9 ; Memory-access Width Register +VDC_HSR = 10 ; Horizontal Sync Register +VDC_HDR = 11 ; Horizontal Display Register +VDC_VPR = 12 ; Vertical synchronous register +VDC_VDW = 13 ; Vertical display register +VDC_VCR = 14 ; Vertical display END position register +VDC_DCR = 15 ; (DMA) Control Register +VDC_SOUR = 16 ; (DMA) Source Register +VDC_DESR = 17 ; (DMA) Destination Register +VDC_LENR = 18 ; (DMA) Length Register +VDC_SATB = 19 ; Sprite Attribute Table + +; VDC port +; Note: absolute addressing mode must be used when writing to this port + +VDC_CTRL = $0000 +VDC_DATA_LO = $0002 +VDC_DATA_HI = $0003 + +; huc6260 - Video Color Encoder (vce) + +; The DAC has a palette of 512 colours. +; bitmap of the palette data is this: 0000000gggrrrbbb. +; You can read and write the DAC-registers. + +VCE = $0400 ; base + +VCE_CTRL = $0400 ; write$00 to reset +VCE_ADDR_LO = $0402 ; LSB of byte offset into palette +VCE_ADDR_HI = $0403 ; MSB of byte offset into palette +VCE_DATA_LO = $0404 ; LSB of 16-bit palette data +VCE_DATA_HI = $0405 ; MSB of 16-bit palette data + +; programmable sound generator (PSG) + +PSG = $0800 ; base + +PSG_CHAN_SELECT = $0800 +PSG_GLOBAL_PAN = $0801 +PSG_FREQ_LO = $0802 +PSG_FREQ_HI = $0803 +PSG_CHAN_CTRL = $0804 +PSG_CHAN_PAN = $0805 +PSG_CHAN_DATA = $0806 +PSG_NOISE = $0807 +PSG_LFO_FREQ = $0808 +PSG_LFO_CTRL = $0809 + +; timer + +TIMER = $0c00 ; base + +TIMER_COUNT = $0c00 +TIMER_CTRL = $0c01 + +JOY_CTRL = $1000 + +IRQ_MASK = $1402 +IRQ_STATUS = $1403 + +CDR_MEM_DISABLE = $1803 +CDR_MEM_ENABLE = $1807 + +; Write VDC register +.macro VREG arg1,arg2 + st0 #arg1 + st1 #<(arg2) + st2 #>(arg2) +.endmacro diff --git a/asminc/pet.inc b/asminc/pet.inc index 1ebf391f9..a745a89c8 100644 --- a/asminc/pet.inc +++ b/asminc/pet.inc @@ -6,6 +6,7 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +VARTAB := $2A ; Pointer to start of BASIC variables MEMSIZE := $34 ; Size of memory installed TXTPTR := $77 ; Pointer into BASIC source code TIME := $8D ; 60HZ clock diff --git a/asminc/plus4.inc b/asminc/plus4.inc index 17e250508..69b2298a3 100644 --- a/asminc/plus4.inc +++ b/asminc/plus4.inc @@ -7,6 +7,8 @@ ; Zero page, Commodore stuff TMPPTR := $22 ; Temporary ptr used by BASIC +VARTAB := $2D ; Pointer to start of BASIC variables +MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1) TXTPTR := $3B ; Pointer into BASIC source code TIME := $A3 ; 60HZ clock FNAM_LEN := $AB ; Length of filename diff --git a/asminc/vic20.inc b/asminc/vic20.inc index c42db4258..12424dc11 100644 --- a/asminc/vic20.inc +++ b/asminc/vic20.inc @@ -6,6 +6,8 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +VARTAB := $2D ; Pointer to start of BASIC variables +MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1) TXTPTR := $7A ; Pointer into BASIC source code TIME := $A0 ; 60HZ clock FNAM_LEN := $B7 ; Length of filename diff --git a/cfg/apple2-overlay.cfg b/cfg/apple2-overlay.cfg index d0b34692f..244e4582f 100644 --- a/cfg/apple2-overlay.cfg +++ b/cfg/apple2-overlay.cfg @@ -18,7 +18,7 @@ SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay __LOADADDR__: type = weak, value = __STARTUP_RUN__; - __LOADSIZE__: type = weak, value = __ZPSAVE_RUN__ - __STARTUP_RUN__ + + __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ + __MOVE_LAST__ - __MOVE_START__; } MEMORY { @@ -45,7 +45,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss, define = yes; + INITBSS: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; LC: load = MOVE, run = LC, type = ro, optional = yes; diff --git a/cfg/apple2-system.cfg b/cfg/apple2-system.cfg index 33ab04f5e..f07208e45 100644 --- a/cfg/apple2-system.cfg +++ b/cfg/apple2-system.cfg @@ -5,7 +5,7 @@ SYMBOLS { __LCSIZE__: type = weak, value = $0C00; # Rest of bank two __STACKSIZE__: type = weak, value = $0800; # 2k stack __LOADADDR__: type = weak, value = __STARTUP_RUN__; - __LOADSIZE__: type = weak, value = __ZPSAVE_RUN__ - __STARTUP_RUN__ + + __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ + __MOVE_LAST__ - __MOVE_START__; } MEMORY { @@ -21,7 +21,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss, define = yes; + INITBSS: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; LC: load = MOVE, run = LC, type = ro, optional = yes; diff --git a/cfg/apple2.cfg b/cfg/apple2.cfg index 5673302d1..27eb706c4 100644 --- a/cfg/apple2.cfg +++ b/cfg/apple2.cfg @@ -10,7 +10,7 @@ SYMBOLS { __LCSIZE__: type = weak, value = $0C00; # Rest of bank two __STACKSIZE__: type = weak, value = $0800; # 2k stack __LOADADDR__: type = weak, value = __STARTUP_RUN__; - __LOADSIZE__: type = weak, value = __ZPSAVE_RUN__ - __STARTUP_RUN__ + + __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ + __MOVE_LAST__ - __MOVE_START__; } MEMORY { @@ -28,7 +28,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss, define = yes; + INITBSS: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; LC: load = MOVE, run = LC, type = ro, optional = yes; diff --git a/cfg/apple2enh-overlay.cfg b/cfg/apple2enh-overlay.cfg index d0b34692f..244e4582f 100644 --- a/cfg/apple2enh-overlay.cfg +++ b/cfg/apple2enh-overlay.cfg @@ -18,7 +18,7 @@ SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay __LOADADDR__: type = weak, value = __STARTUP_RUN__; - __LOADSIZE__: type = weak, value = __ZPSAVE_RUN__ - __STARTUP_RUN__ + + __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ + __MOVE_LAST__ - __MOVE_START__; } MEMORY { @@ -45,7 +45,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss, define = yes; + INITBSS: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; LC: load = MOVE, run = LC, type = ro, optional = yes; diff --git a/cfg/apple2enh-system.cfg b/cfg/apple2enh-system.cfg index 33ab04f5e..f07208e45 100644 --- a/cfg/apple2enh-system.cfg +++ b/cfg/apple2enh-system.cfg @@ -5,7 +5,7 @@ SYMBOLS { __LCSIZE__: type = weak, value = $0C00; # Rest of bank two __STACKSIZE__: type = weak, value = $0800; # 2k stack __LOADADDR__: type = weak, value = __STARTUP_RUN__; - __LOADSIZE__: type = weak, value = __ZPSAVE_RUN__ - __STARTUP_RUN__ + + __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ + __MOVE_LAST__ - __MOVE_START__; } MEMORY { @@ -21,7 +21,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss, define = yes; + INITBSS: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; LC: load = MOVE, run = LC, type = ro, optional = yes; diff --git a/cfg/apple2enh.cfg b/cfg/apple2enh.cfg index 5673302d1..27eb706c4 100644 --- a/cfg/apple2enh.cfg +++ b/cfg/apple2enh.cfg @@ -10,7 +10,7 @@ SYMBOLS { __LCSIZE__: type = weak, value = $0C00; # Rest of bank two __STACKSIZE__: type = weak, value = $0800; # 2k stack __LOADADDR__: type = weak, value = __STARTUP_RUN__; - __LOADSIZE__: type = weak, value = __ZPSAVE_RUN__ - __STARTUP_RUN__ + + __LOADSIZE__: type = weak, value = __INITBSS_RUN__ - __STARTUP_RUN__ + __MOVE_LAST__ - __MOVE_START__; } MEMORY { @@ -28,7 +28,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss, define = yes; + INITBSS: load = RAM, type = bss, define = yes; BSS: load = RAM, type = bss, define = yes; INIT: load = MOVE, run = RAM, type = ro, define = yes, optional = yes; LC: load = MOVE, run = LC, type = ro, optional = yes; diff --git a/cfg/atari-cart.cfg b/cfg/atari-cart.cfg index db9486a9f..58457c606 100644 --- a/cfg/atari-cart.cfg +++ b/cfg/atari-cart.cfg @@ -22,6 +22,7 @@ SEGMENTS { CODE: load = ROM, type = ro, define = yes; RODATA: load = ROM, type = ro, optional = yes; DATA: load = ROM, run = RAM, type = rw, define = yes, optional = yes; + INITBSS: load = RAM, type = bss, optional = yes; BSS: load = RAM, type = bss, define = yes, optional = yes; CARTHDR: load = CARTID, type = ro; ZEROPAGE: load = ZP, type = zp, optional = yes; diff --git a/cfg/atari-cassette.cfg b/cfg/atari-cassette.cfg index 2116aecd0..80b5c695f 100644 --- a/cfg/atari-cassette.cfg +++ b/cfg/atari-cassette.cfg @@ -19,6 +19,7 @@ SEGMENTS { CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro, optional = yes; DATA: load = RAM, type = rw, optional = yes; + INITBSS: load = RAM, type = bss, optional = yes; BSS: load = RAM, type = bss, define = yes, optional = yes; ZEROPAGE: load = ZP, type = zp, optional = yes; EXTZP: load = ZP, type = zp, optional = yes; diff --git a/cfg/atari-overlay.cfg b/cfg/atari-overlay.cfg index 1d339b208..b3abad988 100644 --- a/cfg/atari-overlay.cfg +++ b/cfg/atari-overlay.cfg @@ -49,6 +49,7 @@ SEGMENTS { CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; + INITBSS: load = RAM, type = bss, optional = yes; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; diff --git a/cfg/atari.cfg b/cfg/atari.cfg index dce593f05..97b289d7e 100644 --- a/cfg/atari.cfg +++ b/cfg/atari.cfg @@ -37,6 +37,7 @@ SEGMENTS { CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; + INITBSS: load = RAM, type = bss, optional = yes; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; diff --git a/cfg/atarixl-largehimem.cfg b/cfg/atarixl-largehimem.cfg index 01fc76a26..f96096995 100644 --- a/cfg/atarixl-largehimem.cfg +++ b/cfg/atarixl-largehimem.cfg @@ -70,6 +70,7 @@ SEGMENTS { CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; + INITBSS: load = RAM, type = bss, optional = yes; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; diff --git a/cfg/atarixl-overlay.cfg b/cfg/atarixl-overlay.cfg index 68d0f524e..7356fc03e 100644 --- a/cfg/atarixl-overlay.cfg +++ b/cfg/atarixl-overlay.cfg @@ -82,6 +82,7 @@ SEGMENTS { CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; + INITBSS: load = RAM, type = bss, optional = yes; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; diff --git a/cfg/atarixl.cfg b/cfg/atarixl.cfg index aad3ce613..84992a205 100644 --- a/cfg/atarixl.cfg +++ b/cfg/atarixl.cfg @@ -68,6 +68,7 @@ SEGMENTS { CODE: load = RAM, type = ro, define = yes; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; + INITBSS: load = RAM, type = bss, optional = yes; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; diff --git a/cfg/atmos.cfg b/cfg/atmos.cfg index 137c0e9a9..a1f935efa 100644 --- a/cfg/atmos.cfg +++ b/cfg/atmos.cfg @@ -1,22 +1,31 @@ SYMBOLS { - __STACKSIZE__: type = weak, value = $0800; # 2k stack + __TAPEHDR__: type = import; + __BASHDR__: type = import; + __PROGFLAG__: type = weak, value = $00; # $00=BASIC, $80=machine code + __AUTORUN__: type = weak, value = $00; # $00=only load, $C7=run + __STACKSIZE__: type = weak, value = $0800; # 2K stack + __GRAB__: type = weak, value = 0; # 0=don't grab graphics RAM, 1=grab graphics RAM + __RAMEND__: type = weak, value = $9800 + $1C00 * __GRAB__; } MEMORY { ZP: file = "", define = yes, start = $00E2, size = $001A; - TAPEHDR: file = %O, type = ro, start = $0000, size = $0011; - RAM: file = %O, define = yes, start = $0500, size = $9300 - __STACKSIZE__; + TAPEHDR: file = %O, type = ro, start = $0000, size = $001F; + BASHEAD: file = %O, define = yes, start = $0501, size = $000D; + RAM: file = %O, define = yes, start = __BASHEAD_LAST__, size = __RAMEND__ - __RAM_START__ - __STACKSIZE__; } SEGMENTS { + ZEROPAGE: load = ZP, type = zp; TAPEHDR: load = TAPEHDR, type = ro; + BASHDR: load = BASHEAD, type = ro, define = yes, optional = yes; STARTUP: load = RAM, type = ro; LOWCODE: load = RAM, type = ro, optional = yes; - INIT: load = RAM, type = ro, define = yes, optional = yes; CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; + INIT: load = RAM, type = ro, define = yes, optional = yes; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss, define = yes; + ZPSAVE1: load = RAM, type = rw, define = yes; # ZPSAVE1, ZPSAVE2 must be together + ZPSAVE2: load = RAM, type = bss; # see "libsrc/atmos/crt0.s" BSS: load = RAM, type = bss, define = yes; - ZEROPAGE: load = ZP, type = zp; } FEATURES { CONDES: type = constructor, diff --git a/cfg/c128-overlay.cfg b/cfg/c128-overlay.cfg index e16ad4b2e..f2cc3c40c 100644 --- a/cfg/c128-overlay.cfg +++ b/cfg/c128-overlay.cfg @@ -38,7 +38,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; OVL1ADDR: load = OVL1ADDR, type = ro; diff --git a/cfg/c128.cfg b/cfg/c128.cfg index 0e1259111..ef2aa4184 100644 --- a/cfg/c128.cfg +++ b/cfg/c128.cfg @@ -18,7 +18,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; } diff --git a/cfg/c16.cfg b/cfg/c16.cfg index 78c1739d3..efb42991f 100644 --- a/cfg/c16.cfg +++ b/cfg/c16.cfg @@ -18,7 +18,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; } diff --git a/cfg/c64-overlay.cfg b/cfg/c64-overlay.cfg index 2f7693e6e..1c3b19c09 100644 --- a/cfg/c64-overlay.cfg +++ b/cfg/c64-overlay.cfg @@ -1,64 +1,71 @@ +FEATURES { + STARTADDRESS: default = $0801; +} SYMBOLS { - __LOADADDR__: type = import; - __EXEHDR__: type = import; - __OVERLAYADDR__: type = import; - __STACKSIZE__: type = weak, value = $0800; # 2k stack - __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay + __LOADADDR__: type = import; + __EXEHDR__: type = import; + __OVERLAYADDR__: type = import; + __STACKSIZE__: type = weak, value = $0800; # 2k stack + __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay + __HIMEM__: type = weak, value = $D000; + __OVERLAYSTART__: type = export, value = __HIMEM__ - __OVERLAYSIZE__; } MEMORY { - ZP: file = "", define = yes, start = $0002, size = $001A; - LOADADDR: file = %O, start = $07FF, size = $0002; - HEADER: file = %O, start = $0801, size = $000C; - RAM: file = %O, define = yes, start = $080D, size = $C7F3 - __OVERLAYSIZE__ - __STACKSIZE__; - OVL1ADDR: file = "%O.1", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL1: file = "%O.1", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; - OVL2ADDR: file = "%O.2", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL2: file = "%O.2", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; - OVL3ADDR: file = "%O.3", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL3: file = "%O.3", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; - OVL4ADDR: file = "%O.4", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL4: file = "%O.4", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; - OVL5ADDR: file = "%O.5", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL5: file = "%O.5", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; - OVL6ADDR: file = "%O.6", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL6: file = "%O.6", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; - OVL7ADDR: file = "%O.7", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL7: file = "%O.7", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; - OVL8ADDR: file = "%O.8", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL8: file = "%O.8", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; - OVL9ADDR: file = "%O.9", start = $CFFE - __OVERLAYSIZE__, size = $0002; - OVL9: file = "%O.9", start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; + ZP: file = "", define = yes, start = $0002, size = $001A; + LOADADDR: file = %O, start = %S - 2, size = $0002; + HEADER: file = %O, define = yes, start = %S, size = $000D; + MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __OVERLAYSTART__ - __STACKSIZE__ - __HEADER_LAST__; + MOVE: file = %O, start = __INITBSS_LOAD__, size = __HIMEM__ - __BSS_RUN__; + INIT: file = "", start = __BSS_RUN__, size = __HIMEM__ - __BSS_RUN__; + OVL1ADDR: file = "%O.1", start = __OVERLAYSTART__ - 2, size = $0002; + OVL1: file = "%O.1", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; + OVL2ADDR: file = "%O.2", start = __OVERLAYSTART__ - 2, size = $0002; + OVL2: file = "%O.2", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; + OVL3ADDR: file = "%O.3", start = __OVERLAYSTART__ - 2, size = $0002; + OVL3: file = "%O.3", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; + OVL4ADDR: file = "%O.4", start = __OVERLAYSTART__ - 2, size = $0002; + OVL4: file = "%O.4", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; + OVL5ADDR: file = "%O.5", start = __OVERLAYSTART__ - 2, size = $0002; + OVL5: file = "%O.5", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; + OVL6ADDR: file = "%O.6", start = __OVERLAYSTART__ - 2, size = $0002; + OVL6: file = "%O.6", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; + OVL7ADDR: file = "%O.7", start = __OVERLAYSTART__ - 2, size = $0002; + OVL7: file = "%O.7", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; + OVL8ADDR: file = "%O.8", start = __OVERLAYSTART__ - 2, size = $0002; + OVL8: file = "%O.8", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; + OVL9ADDR: file = "%O.9", start = __OVERLAYSTART__ - 2, size = $0002; + OVL9: file = "%O.9", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; } SEGMENTS { - LOADADDR: load = LOADADDR, type = ro; - EXEHDR: load = HEADER, type = ro; - STARTUP: load = RAM, type = ro; - LOWCODE: load = RAM, type = ro, optional = yes; - INIT: load = RAM, type = ro, define = yes, optional = yes; - CODE: load = RAM, type = ro; - RODATA: load = RAM, type = ro; - DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; - BSS: load = RAM, type = bss, define = yes; - ZEROPAGE: load = ZP, type = zp; - OVL1ADDR: load = OVL1ADDR, type = ro; - OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; - OVL2ADDR: load = OVL2ADDR, type = ro; - OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; - OVL3ADDR: load = OVL3ADDR, type = ro; - OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; - OVL4ADDR: load = OVL4ADDR, type = ro; - OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; - OVL5ADDR: load = OVL5ADDR, type = ro; - OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; - OVL6ADDR: load = OVL6ADDR, type = ro; - OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; - OVL7ADDR: load = OVL7ADDR, type = ro; - OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; - OVL8ADDR: load = OVL8ADDR, type = ro; - OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; - OVL9ADDR: load = OVL9ADDR, type = ro; - OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; + ZEROPAGE: load = ZP, type = zp; + LOADADDR: load = LOADADDR, type = ro; + EXEHDR: load = HEADER, type = ro; + STARTUP: load = MAIN, type = ro; + LOWCODE: load = MAIN, type = ro, optional = yes; + CODE: load = MAIN, type = ro; + RODATA: load = MAIN, type = ro; + DATA: load = MAIN, type = rw; + INITBSS: load = MAIN, type = bss, define = yes; + BSS: load = MAIN, type = bss, define = yes; + INIT: load = MOVE, run = INIT, type = ro, define = yes; + OVL1ADDR: load = OVL1ADDR, type = ro; + OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; + OVL2ADDR: load = OVL2ADDR, type = ro; + OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; + OVL3ADDR: load = OVL3ADDR, type = ro; + OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; + OVL4ADDR: load = OVL4ADDR, type = ro; + OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; + OVL5ADDR: load = OVL5ADDR, type = ro; + OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; + OVL6ADDR: load = OVL6ADDR, type = ro; + OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; + OVL7ADDR: load = OVL7ADDR, type = ro; + OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; + OVL8ADDR: load = OVL8ADDR, type = ro; + OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; + OVL9ADDR: load = OVL9ADDR, type = ro; + OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; } FEATURES { CONDES: type = constructor, diff --git a/cfg/c64.cfg b/cfg/c64.cfg index 5d8befd02..2a105c7f1 100644 --- a/cfg/c64.cfg +++ b/cfg/c64.cfg @@ -1,26 +1,32 @@ +FEATURES { + STARTADDRESS: default = $0801; +} SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack + __HIMEM__: type = weak, value = $D000; } MEMORY { - ZP: file = "", define = yes, start = $0002, size = $001A; - LOADADDR: file = %O, start = $07FF, size = $0002; - HEADER: file = %O, start = $0801, size = $000C; - RAM: file = %O, define = yes, start = $080D, size = $C7F3 - __STACKSIZE__; + ZP: file = "", define = yes, start = $0002, size = $001A; + LOADADDR: file = %O, start = %S - 2, size = $0002; + HEADER: file = %O, define = yes, start = %S, size = $000D; + MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __STACKSIZE__ - __HEADER_LAST__; + MOVE: file = %O, start = __INITBSS_LOAD__, size = __HIMEM__ - __BSS_RUN__; + INIT: file = "", start = __BSS_RUN__, size = __HIMEM__ - __BSS_RUN__; } SEGMENTS { - LOADADDR: load = LOADADDR, type = ro; - EXEHDR: load = HEADER, type = ro; - STARTUP: load = RAM, type = ro; - LOWCODE: load = RAM, type = ro, optional = yes; - INIT: load = RAM, type = ro, define = yes, optional = yes; - CODE: load = RAM, type = ro; - RODATA: load = RAM, type = ro; - DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; - BSS: load = RAM, type = bss, define = yes; - ZEROPAGE: load = ZP, type = zp; + ZEROPAGE: load = ZP, type = zp; + LOADADDR: load = LOADADDR, type = ro; + EXEHDR: load = HEADER, type = ro; + STARTUP: load = MAIN, type = ro; + LOWCODE: load = MAIN, type = ro, optional = yes; + CODE: load = MAIN, type = ro; + RODATA: load = MAIN, type = ro; + DATA: load = MAIN, type = rw; + INITBSS: load = MAIN, type = bss, define = yes; + BSS: load = MAIN, type = bss, define = yes; + INIT: load = MOVE, run = INIT, type = ro, define = yes; } FEATURES { CONDES: type = constructor, diff --git a/cfg/cbm510.cfg b/cfg/cbm510.cfg index 7635c6eeb..d0775b6f2 100644 --- a/cfg/cbm510.cfg +++ b/cfg/cbm510.cfg @@ -22,6 +22,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = rw, define = yes; diff --git a/cfg/cbm610.cfg b/cfg/cbm610.cfg index 48b5eba0c..ae66f4c4a 100644 --- a/cfg/cbm610.cfg +++ b/cfg/cbm610.cfg @@ -19,6 +19,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = rw, define = yes; diff --git a/cfg/osic1p-asm.cfg b/cfg/osic1p-asm.cfg new file mode 100644 index 000000000..4000890be --- /dev/null +++ b/cfg/osic1p-asm.cfg @@ -0,0 +1,25 @@ +FEATURES { + STARTADDRESS: default = $0200; +} +SYMBOLS { +# If you want ld65 to output a loadable-format file by default, then uncomment +# the next line. (Then, "-u __BOOT__" wouldn't be needed on the command line.) +# __BOOT__: type = import; + __STACKSIZE__: type = weak, value = $0400; # 1 kB stack + __HIMEM__: type = weak, value = $8000; # 32 kB RAM +} +MEMORY { + # for size of ZP, see runtime/zeropage.s and c1p/extzp.s + ZP: file = "", define = yes, start = $0002, size = $001A + $0006; + HEAD: file = %O, start = $0000, size = $00B6; + RAM: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S; +} +SEGMENTS { + BOOT: load = HEAD, type = ro, optional = yes; + INIT: load = RAM, type = ro, define = yes, optional = yes; + CODE: load = RAM, type = rw; + RODATA: load = RAM, type = rw; + DATA: load = RAM, type = rw; + BSS: load = RAM, type = bss, define = yes; + ZEROPAGE: load = ZP, type = zp; +} diff --git a/cfg/osic1p.cfg b/cfg/osic1p.cfg new file mode 100644 index 000000000..fd9aa604e --- /dev/null +++ b/cfg/osic1p.cfg @@ -0,0 +1,38 @@ +FEATURES { + STARTADDRESS: default = $0200; +} +SYMBOLS { +# If you want ld65 to output a loadable-format file by default, then uncomment +# the next line. (Then, "-u __BOOT__" wouldn't be needed on the command line.) +# __BOOT__: type = import; + __STACKSIZE__: type = weak, value = $0400; # 1 kB stack + __HIMEM__: type = weak, value = $8000; # 32 kB RAM +} +MEMORY { + # for size of ZP, see runtime/zeropage.s and c1p/extzp.s + ZP: file = "", define = yes, start = $0002, size = $001A + $0020; + HEAD: file = %O, start = $0000, size = $00B6; + RAM: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S; +} +SEGMENTS { + BOOT: load = HEAD, type = ro, optional = yes; + STARTUP: load = RAM, type = ro; + LOWCODE: load = RAM, type = ro, optional = yes; + INIT: load = RAM, type = ro, define = yes, optional = yes; + CODE: load = RAM, type = rw; + RODATA: load = RAM, type = rw; + DATA: load = RAM, type = rw; + BSS: load = RAM, type = bss, define = yes; + ZEROPAGE: load = ZP, type = zp; + EXTZP: load = ZP, type = zp, define = yes, optional = yes; +} +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = INIT; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; +} diff --git a/cfg/pce.cfg b/cfg/pce.cfg new file mode 100644 index 000000000..9128eb727 --- /dev/null +++ b/cfg/pce.cfg @@ -0,0 +1,46 @@ +# linker config to produce simple NEC PC-Engine cartridge (.pce) + +SYMBOLS { + __STACKSIZE__: type = weak, value = $0300; # 3 pages stack +} + +MEMORY { + # FIXME: is this correct? the first 3? bytes cant be used? + ZP: start = $03, size = $fd, type = rw, define = yes; + + # reset-bank and hardware vectors + ROM0: start = $e000, size = $1ff6, file = %O ,fill = yes, define = yes; + ROMV: start = $fff6, size = $a, file = %O,fill = yes; + + # first RAM page (also contains stack and zeropage) + RAM: start = $2200, size = $1e00, define = yes; +} + +SEGMENTS { + STARTUP: load = ROM0, type = ro, define = yes; + INIT: load = ROM0, type = ro, define = yes, optional = yes; + CODE: load = ROM0, type = ro, define = yes; + RODATA: load = ROM0, type = ro, define = yes; + DATA: load = ROM0, run= RAM, type = rw, define = yes; + BSS: load = RAM, type = bss, define = yes; + VECTORS: load = ROMV, type = rw, define = yes; + ZEROPAGE: load = ZP, type = zp, define = yes; + EXTZP: load = ZP, type = zp, define = yes, optional = yes; + APPZP: load = ZP, type = zp, define = yes, optional = yes; +} + +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = INIT; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; + CONDES: type = interruptor, + label = __INTERRUPTOR_TABLE__, + count = __INTERRUPTOR_COUNT__, + segment = RODATA, + import = __CALLIRQ__; +} diff --git a/cfg/pet.cfg b/cfg/pet.cfg index ef8b82e54..80d89ee50 100644 --- a/cfg/pet.cfg +++ b/cfg/pet.cfg @@ -18,7 +18,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; } diff --git a/cfg/plus4.cfg b/cfg/plus4.cfg index c756f45a1..6eeddf12e 100644 --- a/cfg/plus4.cfg +++ b/cfg/plus4.cfg @@ -18,7 +18,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; } diff --git a/cfg/vic20-32k.cfg b/cfg/vic20-32k.cfg index c66b35247..23cd718df 100644 --- a/cfg/vic20-32k.cfg +++ b/cfg/vic20-32k.cfg @@ -20,7 +20,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; } diff --git a/cfg/vic20.cfg b/cfg/vic20.cfg index f356eb61e..9a5ce9a63 100644 --- a/cfg/vic20.cfg +++ b/cfg/vic20.cfg @@ -18,7 +18,7 @@ SEGMENTS { CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; - ZPSAVE: load = RAM, type = bss; + INITBSS: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; } diff --git a/doc/Makefile b/doc/Makefile index 02ed6b1d3..967443ef0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,7 +2,7 @@ ifneq ($(shell echo),) CMD_EXE = 1 endif -.PHONY: all mostlyclean clean install zip doc html info gh-pages +.PHONY: all mostlyclean clean install zip doc html info .SUFFIXES: diff --git a/doc/atmos.sgml b/doc/atmos.sgml index 805fc7a03..68f7f9d65 100644 --- a/doc/atmos.sgml +++ b/doc/atmos.sgml @@ -7,7 +7,7 @@ , , -2014-03-27 +2015-01-09 An overview over the Atmos runtime system as it is implemented for the cc65 C @@ -32,27 +32,39 @@ more than one platform. Please see the function reference for more information. + Binary format

The standard binary output format generated by the linker for the Atmos target -is a machine language program with a 17 byte tape header including a cc65 tag. -The standard load and autostart address is $500. +is a machine language program with a one-line BASIC stub that jumps to the +machine-language part through Memory layout

-In the standard setup, cc65 generated programs use the memory from -$500 to $9800, so nearly 37K of memory (including the stack) is +In the standard setup, cc65-generated programs use the memory from +$0501 to $9800; so, nearly 37K of memory (including the stack) is available. ROM calls are possible without further precautions. +If your program needs more memory, and it won't use TGI graphics, then you can +use the ld65 command-line option,

@@ -90,7 +102,7 @@ structures; accessing the struct fields will access the chip registers. - Access to the VIA (versatile interface adapter) chip is available via the + Access to the VIA (Versatile Interface Adapter) chip is available via the

@@ -117,7 +129,8 @@ The names in the parentheses denote the symbols to be used for static linking of Graphics drivers

-The default drivers, @@ -175,13 +188,14 @@ No mouse drivers are currently available for the Atmos. Disk I/O

-The existing library for the Atmos doesn't implement C file -I/O. There are hacks for the @@ -202,7 +216,14 @@ following functions (and a few others): Function keys

-These are defined to be FUNCT + number key. +They are defined to be FUNCT + a number key. + + +Capitals lock

+ +The keyboard's "CAPS Lock" mode is turned off while the program is running. +The previous mode (usually, CAPS Lock turned on [because Oric BASIC keywords +must be UPPER-case]) is restored when the program stops. Passing arguments to the program

@@ -211,10 +232,12 @@ Command-line arguments can be passed to - CALL#500:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 + RUN:REM arg1 " ARG2 IS QUOTED" ARG3 "" ARG5 +You must turn Arguments are separated by spaces. Arguments may be quoted. Leading and trailing spaces around an argument are ignored. Spaces within @@ -225,6 +248,15 @@ supported directly by BASIC, the following syntax was chosen: +Automatic starting

+ +Usually, a cc65-built program just will sit quietly in memory, after it is +CLOADed. It waits for you to start it (by typing BASIC's Interrupts

The runtime for the Atmos uses routines marked as Extras

+ +80 Columns conio driver

+ +The C64 package comes with an alternative software driven 80 columns +module +cl65 -t c64 myprog.c c64-soft80.o + + +Note that the soft80 conio driver is incompatible with the +80 Columns conio driver (monochrome)

+ +In an (even more) memory constrained situation, a size optimized version of the +software driven 80 columns module may be used, which only supports one common +text color for the whole screen. + + +cl65 -t c64 myprog.c c64-soft80mono.o + Platform-specific header files

@@ -216,6 +249,9 @@ configuration. palette of the 16 C64 colors).

+Note that the graphics drivers are incompatible with the +Extended memory drivers

@@ -241,7 +277,7 @@ configuration. A driver for the hidden RAM below the I/O area and kernal ROM. Supports 48 256 byte pages. Please note that this driver is incompatible with any of the - graphics drivers! + graphics drivers, or the soft80 conio driver! A driver for the RamCart 64/128 written and contributed by Maciej Witkowiak. diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 32cf0b80b..213033cd4 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -2,11 +2,12 @@

ca65 Users Guide -<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> -<date>2014-04-24 +<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:greg.king5@verizon.net" name="Greg King"> +<date>2015-11-17 <abstract> -ca65 is a powerful macro assembler for the 6502, 65C02 and 65816 CPUs. It is +ca65 is a powerful macro assembler for the 6502, 65C02, and 65816 CPUs. It is used as a companion assembler for the cc65 crosscompiler, but it may also be used as a standalone product. </abstract> @@ -430,24 +431,21 @@ The assembler accepts <sect1>65816 mode<p> -In 65816 mode several aliases are accepted in addition to the official +In 65816 mode, several aliases are accepted, in addition to the official mnemonics: <tscreen><verb> - BGE is an alias for BCS - BLT is an alias for BCC - CPA is an alias for CMP - DEA is an alias for DEC A - INA is an alias for INC A - SWA is an alias for XBA - TAD is an alias for TCD - TAS is an alias for TCS - TDA is an alias for TDC - TSA is an alias for TSC +CPA is an alias for CMP +DEA is an alias for DEC A +INA is an alias for INC A +SWA is an alias for XBA +TAD is an alias for TCD +TAS is an alias for TCS +TDA is an alias for TDC +TSA is an alias for TSC </verb></tscreen> - <sect1>6502X mode<label id="6502X-mode"><p> 6502X mode is an extension to the normal 6502 mode. In this mode, several @@ -1194,6 +1192,35 @@ writable. assignments to <tt/*/, use <tt/<ref id=".ORG" name=".ORG">/ instead. +<sect1><tt>.ASIZE</tt><label id=".ASIZE"><p> + + Reading this pseudo variable will return the current size of the + Accumulator in bits. + + For the 65816 instruction set .ASIZE will return either 8 or 16, depending + on the current size of the operand in immediate accu addressing mode. + + For all other CPU instruction sets, .ASIZE will always return 8. + + Example: + + <tscreen><verb> + ; Reverse Subtract with Accumulator + ; A = memory - A + .macro rsb param + .if .asize = 8 + eor #$ff + .else + eor #$ffff + .endif + sec + adc param + .endmacro + </verb></tscreen> + + See also: <tt><ref id=".ISIZE" name=".ISIZE"></tt> + + <sect1><tt>.CPU</tt><label id=".CPU"><p> Reading this pseudo variable will give a constant integer value that @@ -1221,6 +1248,19 @@ writable. </verb></tscreen> +<sect1><tt>.ISIZE</tt><label id=".ISIZE"><p> + + Reading this pseudo variable will return the current size of the Index + register in bits. + + For the 65816 instruction set .ISIZE will return either 8 or 16, depending + on the current size of the operand in immediate index addressing mode. + + For all other CPU instruction sets, .ISIZE will always return 8. + + See also: <tt><ref id=".ASIZE" name=".ASIZE"></tt> + + <sect1><tt>.PARAMCOUNT</tt><label id=".PARAMCOUNT"><p> This builtin pseudo variable is only available in macros. It is replaced by @@ -1279,6 +1319,35 @@ Pseudo functions expect their arguments in parenthesis, and they have a result, either a string or an expression. +<sect1><tt>.ADDRSIZE</tt><label id=".ADDRSIZE"><p> + + The <tt/.ADDRSIZE/ function is used to return the interal address size + associated with a symbol. This can be helpful in macros when knowing the address + size of symbol can help with custom instructions. + + Example: + + <tscreen><verb> + .macro myLDA foo + .if .ADDRSIZE(foo) = 1 + ;do custom command based on zeropage addressing: + .byte 0A5h, foo + .elseif .ADDRSIZE(foo) = 2 + ;do custom command based on absolute addressing: + .byte 0ADh + .word foo + .elseif .ADDRSIZE(foo) = 0 + ; no address size defined for this symbol: + .out .sprintf("Error, address size unknown for symbol %s", .string(foo)) + .endif + .endmacro + </verb></tscreen> + + This command is new and must be enabled with the <tt/.FEATURE addrsize/ command. + + See: <tt><ref id=".FEATURE" name=".FEATURE"></tt> + + <sect1><tt>.BANK</tt><label id=".BANK"><p> The <tt/.BANK/ function is used to support systems with banked memory. The @@ -2287,6 +2356,28 @@ Here's a list of all control commands and a description, what they do: </verb></tscreen> +<sect1><tt>.DEFINEDMACRO</tt><label id=".DEFINEDMACRO"><p> + + Builtin function. The function expects an identifier as argument in braces. + The argument is evaluated, and the function yields "true" if the identifier + has already been defined as the name of a macro. Otherwise the function yields + false. Example: + + <tscreen><verb> + .macro add foo + clc + adc foo + .endmacro + + .if .definedmacro(add) + add #$01 + .else + clc + adc #$01 + .endif + </verb></tscreen> + + <sect1><tt>.DESTRUCTOR</tt><label id=".DESTRUCTOR"><p> Export a symbol and mark it as a module destructor. This may be used @@ -2596,6 +2687,12 @@ Here's a list of all control commands and a description, what they do: <descrip> + <tag><tt>addrsize</tt><label id="addrsize"></tag> + + Enables the .ADDRSIZE pseudo function. This function is experimental and not enabled by default. + + See also: <tt><ref id=".ADDRSIZE" name=".ADDRSIZE"></tt> + <tag><tt>at_in_identifiers</tt><label id="at_in_identifiers"></tag> Accept the at character (`@') as a valid character in identifiers. The @@ -3105,6 +3202,23 @@ Here's a list of all control commands and a description, what they do: the feature in more detail. +<sect1><tt>.ISMNEM, .ISMNEMONIC</tt><label id=".ISMNEMONIC"><p> + + Builtin function. The function expects an identifier as argument in braces. + The argument is evaluated, and the function yields "true" if the identifier + is defined as an instruction mnemonic that is recognized by the assembler. + Example: + + <tscreen><verb> + .if .not .ismnemonic(ina) + .macro ina + clc + adc #$01 + .endmacro + .endif + </verb></tscreen> + + <sect1><tt>.LINECONT</tt><label id=".LINECONT"><p> Switch on or off line continuations using the backslash character @@ -3256,8 +3370,8 @@ Here's a list of all control commands and a description, what they do: atari Defines the scrcode macro. cbm Defines the scrcode macro. cpu Defines constants for the .CPU variable. - generic Defines generic macros like add and sub. - longbranch Defines conditional long jump macros. + generic Defines generic macroes like add, sub, and blt. + longbranch Defines conditional long-jump macroes. </verb></tscreen> Including a macro package twice, or including a macro package that @@ -3596,7 +3710,7 @@ Here's a list of all control commands and a description, what they do: segment, that is, a named section of data. The default segment is "CODE". There may be up to 254 different segments per object file (and up to 65534 per executable). There are shortcut commands for - the most common segments ("CODE", "DATA" and "BSS"). + the most common segments ("ZEROPAGE", "CODE", "RODATA", "DATA", and "BSS"). The command is followed by a string containing the segment name (there are some constraints for the name - as a rule of thumb use only those segment @@ -3630,8 +3744,9 @@ Here's a list of all control commands and a description, what they do: </verb></tscreen> See: <tt><ref id=".BSS" name=".BSS"></tt>, <tt><ref id=".CODE" - name=".CODE"></tt>, <tt><ref id=".DATA" name=".DATA"></tt> and <tt><ref - id=".RODATA" name=".RODATA"></tt> + name=".CODE"></tt>, <tt><ref id=".DATA" name=".DATA"></tt>, <tt><ref + id=".RODATA" name=".RODATA"></tt>, and <tt><ref id=".ZEROPAGE" + name=".ZEROPAGE"></tt> <sect1><tt>.SET</tt><label id=".SET"><p> @@ -3792,7 +3907,7 @@ Here's a list of all control commands and a description, what they do: shortcut for <tscreen><verb> - .segment "ZEROPAGE", zeropage + .segment "ZEROPAGE": zeropage </verb></tscreen> Because of the "zeropage" attribute, labels declared in this segment are @@ -3821,10 +3936,10 @@ In its simplest form, a macro does not have parameters. Here's an example: <tscreen><verb> - .macro asr ; Arithmetic shift right - cmp #$80 ; Put bit 7 into carry - ror ; Rotate right with carry - .endmacro +.macro asr ; Arithmetic shift right + cmp #$80 ; Put bit 7 into carry + ror ; Rotate right with carry +.endmacro </verb></tscreen> The macro above consists of two real instructions, that are inserted into @@ -3832,9 +3947,9 @@ the code, whenever the macro is expanded. Macro expansion is simply done by using the name, like this: <tscreen><verb> - lda $2010 - asr - sta $2010 + lda $2010 + asr + sta $2010 </verb></tscreen> @@ -3843,15 +3958,15 @@ by using the name, like this: When using macro parameters, macros can be even more useful: <tscreen><verb> - .macro inc16 addr - clc - lda addr - adc #$01 - sta addr - lda addr+1 - adc #$00 - sta addr+1 - .endmacro +.macro inc16 addr + clc + lda addr + adc #<$0001 + sta addr + lda addr+1 + adc #>$0001 + sta addr+1 +.endmacro </verb></tscreen> When calling the macro, you may give a parameter, and each occurrence of @@ -3859,19 +3974,19 @@ the name "addr" in the macro definition will be replaced by the given parameter. So <tscreen><verb> - inc16 $1000 + inc16 $1000 </verb></tscreen> will be expanded to <tscreen><verb> - clc - lda $1000 - adc #$01 - sta $1000 - lda $1000+1 - adc #$00 - sta $1000+1 + clc + lda $1000 + adc #<$0001 + sta $1000 + lda $1000+1 + adc #>$0001 + sta $1000+1 </verb></tscreen> A macro may have more than one parameter, in this case, the parameters @@ -3892,40 +4007,40 @@ opposite. Look at this example: <tscreen><verb> - .macro ldaxy a, x, y - .ifnblank a - lda #a - .endif - .ifnblank x - ldx #x - .endif - .ifnblank y - ldy #y - .endif - .endmacro +.macro ldaxy a, x, y +.ifnblank a + lda #a +.endif +.ifnblank x + ldx #x +.endif +.ifnblank y + ldy #y +.endif +.endmacro </verb></tscreen> -This macro may be called as follows: +That macro may be called as follows: <tscreen><verb> - ldaxy 1, 2, 3 ; Load all three registers + ldaxy 1, 2, 3 ; Load all three registers - ldaxy 1, , 3 ; Load only a and y + ldaxy 1, , 3 ; Load only a and y - ldaxy , , 3 ; Load y only + ldaxy , , 3 ; Load y only </verb></tscreen> -There's another helper command for determining, which macro parameters are -valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt> This command is -replaced by the parameter count given, <em/including/ intermediate empty macro +There's another helper command for determining which macro parameters are +valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt>. That command is +replaced by the parameter count given, <em/including/ explicitly empty parameters: <tscreen><verb> - ldaxy 1 ; .PARAMCOUNT = 1 - ldaxy 1,,3 ; .PARAMCOUNT = 3 - ldaxy 1,2 ; .PARAMCOUNT = 2 - ldaxy 1, ; .PARAMCOUNT = 2 - ldaxy 1,2,3 ; .PARAMCOUNT = 3 + ldaxy 1 ; .PARAMCOUNT = 1 + ldaxy 1,,3 ; .PARAMCOUNT = 3 + ldaxy 1,2 ; .PARAMCOUNT = 2 + ldaxy 1, ; .PARAMCOUNT = 2 + ldaxy 1,2,3 ; .PARAMCOUNT = 3 </verb></tscreen> Macro parameters may optionally be enclosed into curly braces. This allows the @@ -3933,19 +4048,19 @@ inclusion of tokens that would otherwise terminate the parameter (the comma in case of a macro parameter). <tscreen><verb> - .macro foo arg1, arg2 - ... - .endmacro +.macro foo arg1, arg2 + ... +.endmacro - foo ($00,x) ; Two parameters passed - foo {($00,x)} ; One parameter passed + foo ($00,x) ; Two parameters passed + foo {($00,x)} ; One parameter passed </verb></tscreen> In the first case, the macro is called with two parameters: '<tt/($00/' -and 'x)'. The comma is not passed to the macro, since it is part of the +and '<tt/x)/'. The comma is not passed to the macro, because it is part of the calling sequence, not the parameters. -In the second case, '($00,x)' is passed to the macro, this time +In the second case, '<tt/($00,x)/' is passed to the macro; this time, including the comma. @@ -3958,17 +4073,17 @@ id=".MATCH" name=".MATCH">/ and <tt/<ref id=".XMATCH" name=".XMATCH">/ functions will allow you to do exactly this: <tscreen><verb> - .macro ldax arg - .if (.match (.left (1, {arg}), #)) - ; immediate mode - lda #<(.right (.tcount ({arg})-1, {arg})) - ldx #>(.right (.tcount ({arg})-1, {arg})) - .else - ; assume absolute or zero page - lda arg - ldx 1+(arg) - .endif - .endmacro +.macro ldax arg + .if (.match (.left (1, {arg}), #)) + ; immediate mode + lda #<(.right (.tcount ({arg})-1, {arg})) + ldx #>(.right (.tcount ({arg})-1, {arg})) + .else + ; assume absolute or zero page + lda arg + ldx 1+(arg) + .endif +.endmacro </verb></tscreen> Using the <tt/<ref id=".MATCH" name=".MATCH">/ function, the macro is able to @@ -3982,11 +4097,11 @@ as end-of-list. The macro can be used as <tscreen><verb> - foo: .word $5678 - ... - ldax #$1234 ; X=$12, A=$34 - ... - ldax foo ; X=$56, A=$78 +foo: .word $5678 +... + ldax #$1234 ; X=$12, A=$34 +... + ldax foo ; X=$56, A=$78 </verb></tscreen> @@ -3995,38 +4110,38 @@ The macro can be used as Macros may be used recursively: <tscreen><verb> - .macro push r1, r2, r3 - lda r1 - pha - .if .paramcount > 1 - push r2, r3 - .endif - .endmacro +.macro push r1, r2, r3 + lda r1 + pha +.ifnblank r2 + push r2, r3 +.endif +.endmacro </verb></tscreen> -There's also a special macro to help writing recursive macros: <tt><ref -id=".EXITMACRO" name=".EXITMACRO"></tt> This command will stop macro expansion -immediately: +There's also a special macro command to help with writing recursive macros: +<tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>. That command will stop macro +expansion immediately: <tscreen><verb> - .macro push r1, r2, r3, r4, r5, r6, r7 - .ifblank r1 - ; First parameter is empty - .exitmacro - .else - lda r1 - pha - .endif - push r2, r3, r4, r5, r6, r7 - .endmacro +.macro push r1, r2, r3, r4, r5, r6, r7 +.ifblank r1 + ; First parameter is empty + .exitmacro +.else + lda r1 + pha +.endif + push r2, r3, r4, r5, r6, r7 +.endmacro </verb></tscreen> -When expanding this macro, the expansion will push all given parameters +When expanding that macro, the expansion will push all given parameters until an empty one is encountered. The macro may be called like this: <tscreen><verb> - push $20, $21, $32 ; Push 3 ZP locations - push $21 ; Push one ZP location + push $20, $21, $32 ; Push 3 ZP locations + push $21 ; Push one ZP location </verb></tscreen> @@ -4037,27 +4152,27 @@ Now, with recursive macros, <tt><ref id=".IFBLANK" name=".IFBLANK"></tt> and Have a look at the inc16 macro above. Here is it again: <tscreen><verb> - .macro inc16 addr - clc - lda addr - adc #$01 - sta addr - lda addr+1 - adc #$00 - sta addr+1 - .endmacro +.macro inc16 addr + clc + lda addr + adc #<$0001 + sta addr + lda addr+1 + adc #>$0001 + sta addr+1 +.endmacro </verb></tscreen> If you have a closer look at the code, you will notice, that it could be written more efficiently, like this: <tscreen><verb> - .macro inc16 addr - inc addr - bne Skip - inc addr+1 - Skip: - .endmacro +.macro inc16 addr + inc addr + bne Skip + inc addr+1 +Skip: +.endmacro </verb></tscreen> But imagine what happens, if you use this macro twice? Since the label "Skip" @@ -4069,27 +4184,27 @@ local variables are replaced by a unique name in each separate macro expansion. So we can solve the problem above by using <tt/.LOCAL/: <tscreen><verb> - .macro inc16 addr - .local Skip ; Make Skip a local symbol - inc addr - bne Skip - inc addr+1 - Skip: ; Not visible outside - .endmacro +.macro inc16 addr + .local Skip ; Make Skip a local symbol + inc addr + bne Skip + inc addr+1 +Skip: ; Not visible outside +.endmacro </verb></tscreen> Another solution is of course to start a new lexical block inside the macro that hides any labels: <tscreen><verb> - .macro inc16 addr - .proc - inc addr - bne Skip - inc addr+1 - Skip: - .endproc - .endmacro +.macro inc16 addr +.proc + inc addr + bne Skip + inc addr+1 +Skip: +.endproc +.endmacro </verb></tscreen> @@ -4126,7 +4241,7 @@ different: be omitted. <item> Since <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may not - contain end-of-line tokens, there are things that cannot be done. They + contain end-of-line tokens, there are things that cannot be done. They may not contain several processor instructions for example. So, while some things may be done with both macro types, each type has special usages. The types complement each other. @@ -4140,27 +4255,27 @@ To emulate assemblers that use "<tt/EQU/" instead of "<tt/=/" you may use the following <tt/.DEFINE/: <tscreen><verb> - .define EQU = +.define EQU = - foo EQU $1234 ; This is accepted now +foo EQU $1234 ; This is accepted now </verb></tscreen> You may use the directive to define string constants used elsewhere: <tscreen><verb> - ; Define the version number - .define VERSION "12.3a" +; Define the version number +.define VERSION "12.3a" - ; ... and use it - .asciiz VERSION + ; ... and use it + .asciiz VERSION </verb></tscreen> Macros with parameters may also be useful: <tscreen><verb> - .define DEBUG(message) .out message +.define DEBUG(message) .out message - DEBUG "Assembling include file #3" + DEBUG "Assembling include file #3" </verb></tscreen> Note that, while formal parameters have to be placed in braces, this is @@ -4169,12 +4284,12 @@ detect the end of one parameter, only the first token is used. If you don't like that, use classic macros instead: <tscreen><verb> - .macro DEBUG message - .out message - .endmacro +.macro DEBUG message + .out message +.endmacro </verb></tscreen> -(This is an example where a problem can be solved with both macro types). +(That is an example where a problem can be solved with both macro types). <sect1>Characters in macros<p> @@ -4194,12 +4309,12 @@ be sure to take the translation into account. <sect1>Deleting macros<p> Macros can be deleted. This will not work if the macro that should be deleted -is currently expanded as in the following non working example: +is currently expanded as in the following non-working example: <tscreen><verb> - .macro notworking - .delmacro notworking - .endmacro +.macro notworking + .delmacro notworking +.endmacro notworking ; Will not work </verb></tscreen> @@ -4210,19 +4325,19 @@ for <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros, <tt><ref id=".UNDEFINE" name=".UNDEFINE"></tt> must be used. Example: <tscreen><verb> - .define value 1 - .macro mac - .byte 2 - .endmacro +.define value 1 +.macro mac + .byte 2 +.endmacro - .byte value ; Emit one byte with value 1 - mac ; Emit another byte with value 2 + .byte value ; Emit one byte with value 1 + mac ; Emit another byte with value 2 - .undefine value - .delmacro mac +.undefine value +.delmacro mac - .byte value ; Error: Unknown identifier - mac ; Error: Missing ":" + .byte value ; Error: Unknown identifier + mac ; Error: Missing ":" </verb></tscreen> A separate command for <tt>.DEFINE</tt> style macros was necessary, because @@ -4234,6 +4349,7 @@ argument to <tt>.UNDEFINE</tt> is not allowed to come from another different commands increases flexibility. + <sect>Macro packages<label id="macropackages"><p> Using the <tt><ref id=".MACPACK" name=".MACPACK"></tt> directive, predefined @@ -4243,48 +4359,47 @@ are: <sect1><tt>.MACPACK generic</tt><p> -This macro package defines macros that are useful in almost any program. -Currently defined macros are: +This macro package defines macroes that are useful in almost any program. +Currently defined macroes are: <tscreen><verb> - .macro add Arg + .macro add Arg ; add without carry clc adc Arg .endmacro - .macro sub Arg + .macro sub Arg ; subtract without borrow sec sbc Arg .endmacro - .macro bge Arg + .macro bge Arg ; branch on greater-than or equal bcs Arg .endmacro - .macro blt Arg + .macro blt Arg ; branch on less-than bcc Arg .endmacro - .macro bgt Arg + .macro bgt Arg ; branch on greater-than .local L beq L bcs Arg L: .endmacro - .macro ble Arg + .macro ble Arg ; branch on less-than or equal beq Arg bcc Arg .endmacro - .macro bnz Arg + .macro bnz Arg ; branch on not zero bne Arg .endmacro - .macro bze Arg + .macro bze Arg ; branch on zero beq Arg .endmacro - </verb></tscreen> @@ -4384,7 +4499,7 @@ it is possible to determine if the instruction is supported, which is the case for the 65SC02, 65C02 and 65816 CPUs (the latter two are upwards compatible to the 65SC02). - + <sect1><tt>.MACPACK module</tt><p> This macro package defines a macro named <tt/module_header/. It takes an @@ -4418,6 +4533,7 @@ compiler, depending on the target system selected: <item><tt/__LUNIX__/ - Target system is <tt/lunix/ <item><tt/__LYNX__/ - Target system is <tt/lynx/ <item><tt/__NES__/ - Target system is <tt/nes/ +<item><tt/__OSIC1P__/ - Target system is <tt/osic1p/ <item><tt/__PET__/ - Target system is <tt/pet/ <item><tt/__PLUS4__/ - Target system is <tt/plus4/ <item><tt/__SIM6502__/ - Target system is <tt/sim6502/ @@ -4748,6 +4864,3 @@ freely, subject to the following restrictions: </article> - - - diff --git a/doc/cc65.sgml b/doc/cc65.sgml index a6b4a07ee..9198d6982 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -3,7 +3,7 @@ <article> <title>cc65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> -<date>2000-09-03, 2001-10-02, 2005-08-01 +<date>2015-05-26 <abstract> cc65 is a C compiler for 6502 targets. It supports several 6502 based home @@ -74,6 +74,7 @@ Short options: Long options: --add-source Include source as comment + --all-cdecl Make functions default to __cdecl__ --bss-name seg Set the name of the BSS segment --check-stack Generate stack overflow checks --code-name seg Set the name of the CODE segment @@ -114,6 +115,14 @@ Here is a description of all the command line options: <descrip> + <tag><tt>--all-cdecl</tt></tag> + + Tells the compiler that functions which aren't declared explicitly with + either the <tt/__cdecl__/ or <tt/__fastcall__/ calling conventions should + have the cdecl convention. (Normally, functions that aren't variadic are + fast-called.) + + <label id="option-bss-name"> <tag><tt>--bss-name seg</tt></tag> @@ -348,6 +357,7 @@ Here is a description of all the command line options: <item>lunix <item>lynx <item>nes + <item>osic1p <item>pet (all CBM PET systems except the 2001) <item>plus4 <item>sim6502 @@ -549,9 +559,10 @@ and the one defined by the ISO standard: be passed as parameters by value. However, struct assignment *is* possible. <p> -<item> Part of the C library is available only with fastcall calling - conventions (see below). It means that you must not mix pointers to - those functions with pointers to user-written, not-fastcall functions. +<item> Most of the C library is available with only the fastcall calling + convention (<ref id="extension-fastcall" name="see below">). It means + that you must not mix pointers to those functions with pointers to + user-written, cdecl functions (the calling conventions are incompatible). <p> <item> The <tt/volatile/ keyword doesn't have an effect. This is not as bad as it sounds, since the 6502 has so few registers that it isn't @@ -589,30 +600,58 @@ This cc65 version has some extensions to the ISO C standard. <ref id="inline-asm" name="see there">. <p> -<item> There is a special calling convention named "fastcall". - The syntax for a function declaration using fastcall is +<label id="extension-fastcall"> +<item> The normal calling convention -- for non-variadic functions -- is + named "fastcall". The syntax for a function declaration that + <em/explicitly/ uses fastcall is <tscreen><verb> <return type> fastcall <function name> (<parameter list>) </verb></tscreen> or <tscreen><verb> - <return type> __fastcall__ <function name> (<parameter list>) + <return type> __fastcall__ <function name> (<parameter list>) </verb></tscreen> - An example would be + An example is <tscreen><verb> - void __fastcall__ f (unsigned char c) + void __fastcall__ f (unsigned char c) </verb></tscreen> The first form of the fastcall keyword is in the user namespace and can therefore be disabled with the <tt><ref id="option--standard" name="--standard"></tt> command line option. - For functions declared as <tt/fastcall/, the rightmost parameter is not + For functions that are <tt/fastcall/, the rightmost parameter is not pushed on the stack but left in the primary register when the function - is called. This will reduce the cost when calling assembler functions - significantly, especially when the function itself is rather small. + is called. That significantly reduces the cost of calling those functions. + <newline><newline> <p> +<item> There is another calling convention named "cdecl". Variadic functions + (their prototypes have an ellipsis [<tt/.../]) always use that + convention. The syntax for a function declaration using cdecl is + + <tscreen><verb> + <return type> cdecl <function name> (<parameter list>) + </verb></tscreen> + or + <tscreen><verb> + <return type> __cdecl__ <function name> (<parameter list>) + </verb></tscreen> + An example is + <tscreen><verb> + int* __cdecl__ f (unsigned char c) + </verb></tscreen> + + The first form of the cdecl keyword is in the user namespace; + and therefore, can be disabled with the <tt/<ref id="option--standard" + name="--standard">/ command-line option. + + For functions that are <tt/cdecl/, the rightmost parameter is pushed + onto the stack before the function is called. That increases the cost + of calling those functions, especially when they are called from many + places.<newline><newline> + <p> + <item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/. Both refer to the primary register that is used by the compiler to evaluate expressions or return function results. <tt/__AX__/ is of @@ -819,6 +858,11 @@ The compiler defines several macros at startup: Is defined if the compiler was called with the <tt/-Os/ command line option. + <tag><tt>__OSIC1P__</tt></tag> + + This macro is defined if the target is the Ohio Scientific Challenger 1P + (-t osic1p). + <tag><tt>__PET__</tt></tag> This macro is defined if the target is the PET family of computers (-t pet). diff --git a/doc/chrcvt.sgml b/doc/chrcvt.sgml new file mode 100644 index 000000000..848fb529d --- /dev/null +++ b/doc/chrcvt.sgml @@ -0,0 +1,116 @@ +<!doctype linuxdoc system> <!-- -*- text-mode -*- --> + +<article> +<title>chrcvt Users Guide +<author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> +<date>2013-02-10 + +<abstract> +chrcvt is the vector font converter. It is able to convert a foreign font into +the native format. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + + +<sect>Overview<p> + +chrcvt is a vector font converter. It is able to convert a "BGI Stroked +Font" to a compact TGI native vector font. See the function <url +url="funcref.html#tgi_load_vectorfont" name="tgi_load_vectorfont"> for usage. + + + +<sect>Usage<p> + +The chrcvt utility converts the font of one Borland file to its cc65 equivalent. + + +<sect1>Command line option overview<p> + +The program may be called as follows: + +<tscreen><verb> +--------------------------------------------------------------------------- +Usage: chrcvt [options] file [options] [file] +Short options: + -h Help (this text) + -v Be more verbose + -V Print the version number and exit + +Long options: + --help Help (this text) + --verbose Be more verbose + --version Print the version number and exit +--------------------------------------------------------------------------- +</verb></tscreen> + + +<sect1>Command line options in detail<p> + +Here is a description of all the command line options: + +<descrip> + + <tag><tt>-v, --verbose</tt></tag> + + Increase the converter verbosity. + + + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <tag><tt>-V, --version</tt></tag> + + Print the version number of the utility. When submitting a bug report, + please include the operating system you're using, and the compiler + version. +</descrip> + + +<sect>Input and output<p> + +The converter will read one CHR file per invocation and write the font +in TCH format to a new file. + +Example output for the command +<tscreen><verb> +chrcvt --verbose LITT.CHR +</verb></tscreen> +<tscreen><verb> +BGI Stroked Font V1.1 - Aug 12, 1991 +Copyright (c) 1987,1988 Borland International +</verb></tscreen> + + + +<sect>Copyright<p> + +chrcvt is (C) Copyright 2009, Ullrich von Bassewitz. For usage of the +binaries and/or sources the following conditions apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/customizing.sgml b/doc/customizing.sgml index 23cf8c5e8..0a0b8c87e 100644 --- a/doc/customizing.sgml +++ b/doc/customizing.sgml @@ -3,7 +3,7 @@ <article> <title>Defining a Custom cc65 Target <author>Bruce Reidenbach -<date>2010-02-22 +<date>2015-03-13 <abstract> This section provides step-by-step instructions on how to use the cc65 @@ -525,15 +525,16 @@ The first step in creating the assembly language code for the driver is to determine how to pass the C arguments to the assembly language routine. The cc65 toolset allows the user to specify whether the data is passed to a subroutine via the stack or by the processor registers by -using the <tt>__fastcall__</tt> function declaration (note that there -are two underscore characters in front of and two behind the -<tt>fastcall</tt> declaration). When <tt>__fastcall__</tt> is -specified, the rightmost argument in the function call is passed to the +using the <tt/__fastcall__/ and <tt/__cdecl__/ function qualifiers (note that +there are two underscore characters in front of and two behind each +qualifier). <tt/__fastcall__/ is the default. When <tt/__cdecl__/ <em/isn't/ +specified, and the function isn't variadic (i.e., its prototype doesn't have +an ellipsis), the rightmost argument in the function call is passed to the subroutine using the 6502 registers instead of the stack. Note that if there is only one argument in the function call, the execution overhead required by the stack interface routines is completely avoided. -Without <tt>__fastcall__</tt>, the argument is loaded in the A and X +With <tt/__cdecl__</tt>, the last argument is loaded into the A and X registers and then pushed onto the stack via a call to <tt>pushax</tt>. The first thing the subroutine does is retrieve the argument from the stack via a call to <tt>ldax0sp</tt>, which copies the values into the A @@ -561,7 +562,7 @@ _foo: jsr ldax0sp ; Retrieve A and X from the stack jmp incsp2 ; Pop A and X from the stack (includes return) </verb></tscreen> -If <tt>__fastcall__</tt> is specified, the argument is loaded into the A +If <tt/__cdecl__/ isn't specified, then the argument is loaded into the A and X registers as before, but the subroutine is then called immediately. The subroutine does not need to retrieve the argument since the value is already available in the A and X registers. diff --git a/doc/da65.sgml b/doc/da65.sgml index 2b8cdb2a3..df8cd7772 100644 --- a/doc/da65.sgml +++ b/doc/da65.sgml @@ -2,12 +2,14 @@ <article> <title>da65 Users Guide -<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> -<date>2003-08-08 +<author> +<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> +<url url="mailto:greg.king5@verizon.net" name="Greg King"> +<date>2014-11-23 <abstract> -da65 is a 6502/65C02 disassembler that is able to read user supplied -information about its input data for better results. The output is ready for +da65 is a 6502/65C02 disassembler that is able to read user-supplied +information about its input data, for better results. The output is ready for feeding into ca65, the macro assembler supplied with the cc65 C compiler. </abstract> @@ -23,7 +25,7 @@ the cc65 C compiler and generates output that is suitable for the ca65 macro assembler. Besides generating output for ca65, one of the design goals was that the user -is able to feed additional information about the code into the disassembler +is able to feed additional information about the code into the disassembler, for improved results. This information may include the location and size of tables, and their format. @@ -106,11 +108,16 @@ Here is a description of all the command line options: <tag><tt>--cpu type</tt></tag> Set the CPU type. The option takes a parameter, which may be one of + <itemize> + <item>6502 + <item>6502x + <item>65sc02 + <item>65c02 + <item>huc6280 + </itemize> - 6502, 6502x, 65sc02, 65c02, huc6280 - - 6502x is the NMOS 6502 with illegal opcodes. huc6280 is the CPU of the PC - engine. Support for the 65816 is currently not available. + 6502x is for the NMOS 6502 with unofficial opcodes. huc6280 is the CPU of + the PC engine. Support for the 65816 currently is not available. <label id="option--formfeeds"> @@ -125,7 +132,7 @@ Here is a description of all the command line options: <tag><tt>-g, --debug-info</tt></tag> This option adds the <tt/.DEBUGINFO/ command to the output file, so the - assembler will generate debug information when reassembling the generated + assembler will generate debug information when re-assembling the generated output. @@ -241,7 +248,7 @@ unsupported. The disassembler works by creating an attribute map for the whole address space ($0000 - $FFFF). Initially, all attributes are cleared. Then, an external info file (if given) is read. Disassembly is done in several passes. -In all passes with the exception of the last one, information about the +In all passes, with the exception of the last one, information about the disassembled code is gathered and added to the symbol and attribute maps. The last pass generates output using the information from the maps. @@ -275,19 +282,19 @@ braces. Attributes have a name followed by a value. The syntax of the value depends on the type of the attribute. String attributes are places in double quotes, numeric attributes may be specified as decimal numbers or hexadecimal with a leading dollar sign. There are also attributes where the attribute -value is a keyword, in this case the keyword is given as is (without quotes or +value is a keyword; in this case, the keyword is given as-is (without quotes or anything). Each attribute is terminated by a semicolon. <tscreen><verb> - group-name { attribute1 attribute-value; attribute2 attribute-value; } + group-name { attribute1 attribute-value; attribute2 attribute-value; } </verb></tscreen> <sect1>Comments<p> -Comments start with a hash mark (<tt/#/) and extend from the position of +Comments start with a hash mark (<tt/#/); and, extend from the position of the mark to the end of the current line. Hash marks inside of strings will -of course <em/not/ start a comment. +<em/not/ start a comment, of course. <sect1>Specifying global options<label id="global-options"><p> @@ -543,18 +550,17 @@ disassembled code. The following attributes are recognized: <tag><tt>END</tt></tag> Followed by a numerical value. Specifies the end address of the segment. The - end address is last the address that is part of the segment. + end address is the last address that is a part of the segment. <tag><tt>NAME</tt></tag> The attribute is followed by a string value which gives the name of the segment. </descrip> -All attributes are mandatory. Segments may not overlap. Since there is no -explicit "end this segment" pseudo op, the disassembler cannot notify the -assembler that one segment has ended. This may lead to errors if you don't -define your segments carefully. As a rule of thumb, if you're using segments, -your should define segments for all disassembled code. +All attributes are mandatory. Segments must not overlap. The disassembler will +change back to the (default) <tt/.code/ segment after the end of each defined +segment. That might not be what you want. As a rule of thumb, if you're using +segments, you should define segments for all disassembled code. <sect1>Specifying Assembler Includes<label id="infofile-asminc"><p> @@ -563,8 +569,8 @@ The <tt/ASMINC/ directive is used to give the names of input files containing symbol assignments in assembler syntax: <tscreen><verb> - Name = value - Name := value + Name = value + Name := value </verb></tscreen> The usual conventions apply for symbol names. Values may be specified as hex @@ -613,48 +619,46 @@ directives explained above: }; # One segment for the whole stuff - SEGMENT { START $E000; END $FFFF; NAME kernal; }; + SEGMENT { START $E000; END $FFFF; NAME "kernal"; }; - RANGE { START $E612; END $E631; TYPE Code; }; - RANGE { START $E632; END $E640; TYPE ByteTable; }; - RANGE { START $EA51; END $EA84; TYPE RtsTable; }; - RANGE { START $EC6C; END $ECAB; TYPE RtsTable; }; - RANGE { START $ED08; END $ED11; TYPE AddrTable; }; + RANGE { START $E612; END $E631; TYPE Code; }; + RANGE { START $E632; END $E640; TYPE ByteTable; }; + RANGE { START $EA51; END $EA84; TYPE RtsTable; }; + RANGE { START $EC6C; END $ECAB; TYPE RtsTable; }; + RANGE { START $ED08; END $ED11; TYPE AddrTable; }; - # Zero page variables - LABEL { NAME "fnadr"; ADDR $90; SIZE 3; }; - LABEL { NAME "sal"; ADDR $93; }; - LABEL { NAME "sah"; ADDR $94; }; - LABEL { NAME "sas"; ADDR $95; }; + # Zero-page variables + LABEL { NAME "fnadr"; ADDR $90; SIZE 3; }; + LABEL { NAME "sal"; ADDR $93; }; + LABEL { NAME "sah"; ADDR $94; }; + LABEL { NAME "sas"; ADDR $95; }; # Stack - LABEL { NAME "stack"; ADDR $100; SIZE 255; }; + LABEL { NAME "stack"; ADDR $100; SIZE 255; }; # Indirect vectors - LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ - LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK - LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI + LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ + LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK + LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI # Jump table at end of kernal ROM - LABEL { NAME "kscrorg"; ADDR $FFED; }; - LABEL { NAME "kplot"; ADDR $FFF0; }; - LABEL { NAME "kiobase"; ADDR $FFF3; }; - LABEL { NAME "kgbye"; ADDR $FFF6; }; + LABEL { NAME "kscrorg"; ADDR $FFED; }; + LABEL { NAME "kplot"; ADDR $FFF0; }; + LABEL { NAME "kiobase"; ADDR $FFF3; }; + LABEL { NAME "kgbye"; ADDR $FFF6; }; # Hardware vectors - LABEL { NAME "hanmi"; ADDR $FFFA; }; - LABEL { NAME "hares"; ADDR $FFFC; }; - LABEL { NAME "hairq"; ADDR $FFFE; }; + LABEL { NAME "hanmi"; ADDR $FFFA; }; + LABEL { NAME "hares"; ADDR $FFFC; }; + LABEL { NAME "hairq"; ADDR $FFFE; }; </verb></tscreen> - - <sect>Copyright<p> -da65 (and all cc65 binutils) are (C) Copyright 1998-2007 Ullrich von -Bassewitz. For usage of the binaries and/or sources the following +da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von +Bassewitz. For usage of the binaries and/or sources, the following conditions do apply: This software is provided 'as-is', without any expressed or implied @@ -666,20 +670,16 @@ including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: <enum> -<item> The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -<item> Altered source versions must be plainly marked as such, and must not - be misrepresented as being the original software. -<item> This notice may not be removed or altered from any source - distribution. +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. </enum> </article> - - - - diff --git a/doc/funcref.sgml b/doc/funcref.sgml index 60b8360ed..a2ccf6c73 100644 --- a/doc/funcref.sgml +++ b/doc/funcref.sgml @@ -3,7 +3,7 @@ <article> <title>cc65 function reference <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> -<date>2014-05-26 +<date>2015-07-21 <abstract> cc65 is a C compiler for 6502 based systems. This function reference describes @@ -39,7 +39,7 @@ Each entry for a function contains a detailed description <tag/Declaration/Describes the needed header files and declaration of the function. <tag/Description/Description of the function. -<tag/Limits/Limits. +<tag/Notes/Notes on the function. <tag/Availability/The availability of the function. <tag/See also/Other related functions. <tag/Example/A piece of actual code using the function. @@ -744,8 +744,7 @@ communication. <tag/Description/The function is called with the type of a directory entry taken from a <tt/struct dirent/ and returns true if the entry designates a directory. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/cc65 @@ -768,8 +767,7 @@ a directory. <tag/Description/The function is called with the type of a directory entry taken from a <tt/struct dirent/ and returns true if the entry designates a disk label. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/cc65 @@ -792,8 +790,7 @@ a disk label. <tag/Description/The function is called with the type of a directory entry taken from a <tt/struct dirent/ and returns true if the entry designates a link. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/cc65 @@ -816,8 +813,7 @@ a link. <tag/Description/The function is called with the type of a directory entry taken from a <tt/struct dirent/ and returns true if the entry designates a regular file. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. <item>A "regular file" means anything with data in it. This might still mean that special processing is needed, when accessing the file. Relative files of @@ -841,10 +837,11 @@ the CBM systems are classified as being "regular" files, for example. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void __fastcall__ _heapadd (void* mem, size_t size);/ <tag/Description/The function adds a block of raw memory to the heap. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The minimum blocksize that can be added is 6 bytes; the function will ignore smaller blocks. +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -870,10 +867,11 @@ ignore smaller blocks. <tag/Description/The function returns the size of a block that must have previously been allocated by <tt/<ref id="malloc" name="malloc">/, <tt/<ref id="calloc" name="calloc">/ or <tt/<ref id="realloc" name="realloc">/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>Passing a pointer to a block that was is not the result of one of the allocation functions, or that has been free'd will give unpredicable results. +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -918,11 +916,10 @@ be allocated from the heap using <tt/<ref id="malloc" name="malloc">/. <descrip> <tag/Function/Return the total available space on the heap. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ -<tag/Declaration/<tt/size_t __fastcall__ _heapmemavail (void);/ +<tag/Declaration/<tt/size_t _heapmemavail (void);/ <tag/Description/The function returns the total number of bytes available on the heap. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>This function is of less use than usually assumed, since the returned heap space may be available but not in one block. So even if this function says that several times more heap space is available than needed, <ref @@ -955,8 +952,7 @@ a colon and a blank. Then the error message for the current contents of <tt/_oserror/ are printed followed by a newline. The message output is the same as returned by <tt/<ref id="_stroserror" name="_stroserror">/ with an argument of <tt/_oserror/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>Since operating system specific error code are - you guessed it - operating system specific, the value in <tt/_oserror/ and the message that is printed depends on the cc65 target. @@ -982,7 +978,7 @@ be used in presence of a prototype. <tag/Description/The function initializes the random number generator with a seed derived from fast changing hardware events, so the seed itself can be considered random to a certain degree. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The randomness of the seed depends on the machine hardware. </itemize> <tag/Availability/cc65 @@ -1003,7 +999,7 @@ considered random to a certain degree. <tag/Declaration/<tt/const char* __fastcall__ _stroserror (unsigned char errcode);/ <tag/Description/<tt/_stroserror/ will return a string describing the given operating system specific error code. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Since operating system specific error code are - you guessed it - operating system specific, the parameter and the string returned depend on the cc65 target. @@ -1028,7 +1024,7 @@ used in presence of a prototype. <tag/Description/<tt/_swap/ will swap (exchange) the contents of the two memory areas pointed to by <tt/p/ and <tt/q/. Both memory areas are assumed to be <tt/size/ bytes in size. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The memory areas may not overlap, otherwise the results are undefined. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. @@ -1054,7 +1050,7 @@ specified in the <tt/pc/ member of the passed <tt/regs/ structure. All registers and the CPU flags are set to the values given in the <tt/regs/ structure. On return from the subroutine, the new values of the registers and flags are stored back overwriting the old values. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Bits 4 and 5 of the flags value in the <tt/regs/ structure are ignored when calling the subroutine (they are unchanged from their current values). <item>The function is only available as fastcall function, so it may only be @@ -1075,7 +1071,7 @@ used in presence of a prototype. <tag/Declaration/<tt/void BRK (void);/ <tag/Description/The function will insert a 6502 BRK instruction into the code which may be used to trigger a debugger. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. <item>The inserted instruction may lead to unexpected results if no debugger is present. @@ -1099,7 +1095,7 @@ is present. <tag/Description/The function will insert a 6502 CLI instruction into the code, so interrupts are enabled. Enabling interrupts has no effects if they are already enabled (the default). -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. <item>Disabling interrupts may lead to unexpected results. </itemize> @@ -1121,7 +1117,7 @@ already enabled (the default). <tag/Declaration/<tt/unsigned char PEEK (unsigned addr);/ <tag/Description/The function will read the absolute memory given by <tt/addr/ and return the value read. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. <item>This function depends highly on the platform and environment. </itemize> @@ -1144,7 +1140,7 @@ and return the value read. <tag/Description/The function will read the absolute memory given by <tt/addr/ and return the value read. The byte read from the higher address is the high byte of the return value. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. <item>This function depends highly on the platform and environment. <item>The order in which the two bytes are read is unspecified and may @@ -1168,7 +1164,7 @@ depend of the address expression used. <tag/Declaration/<tt/void POKE (unsigned addr, unsigned char val);/ <tag/Description/The function writes the value <tt/val/ to the absolute memory address given by <tt/addr/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. <item>This function depends highly on the platform and environment. <item>Careless use will cause the program to act strange or may crash the @@ -1193,7 +1189,7 @@ machine. <tag/Description/The function writes the value <tt/val/ to the absolute memory address given by <tt/addr/. The low byte of <tt/val/ is written to the <tt/addr/, the high byte is written to <tt/addr+1/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. <item>This function depends highly on the platform and environment. <item>Careless use will cause the program to act strange or may crash the @@ -1220,7 +1216,7 @@ depend of the address expression used. <tag/Description/The function will insert a 6502 SEI instruction into the code, so interrupts are disabled. Note that non maskable interrupts cannot be disabled. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. <item>Disabling interrupts may lead to unexpected results. </itemize> @@ -1261,7 +1257,7 @@ on stderr, then terminates the program with an exit code of 3. <tag/Declaration/<tt/int __fastcall__ abs (int v);/ <tag/Description/<tt/abs/ returns the absolute value of the argument passed to the function. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The return value is undefined if <tt/INT_MIN/ is passed to the function. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. @@ -1284,7 +1280,7 @@ used in presence of a prototype. <tag/Description/<tt/assert/ is a macro that expands to a <tt/id/ statement. If the condition evaluates t zero (false), assert prints a message on stderr and aborts the program. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/ISO 9899 @@ -1308,7 +1304,7 @@ on stderr and aborts the program. terminates, they are called in LIFO order (the last function registered is called first). <tt/atexit/ returns zero on success and a nonzero value on failure. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>A maximum of 5 exit functions can be registered. <item>There is no way to unregister an exit function. <item>The function is only available as fastcall function, so it may only be @@ -1331,6 +1327,10 @@ used in presence of a prototype. <tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ <tag/Declaration/<tt/void __fastcall__ atmos_load(const char* name);/ <tag/Description/<tt/atmos_load/ reads a memory block from tape. +<tag/Notes/<itemize> +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. +</itemize> <tag/Availability/cc65 <tag/See also/ <ref id="atmos_save" name="atmos_save"> @@ -1347,6 +1347,10 @@ used in presence of a prototype. <tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ <tag/Declaration/<tt/void __fastcall__ atmos_save(const char* name, const void* start, const void* end);/ <tag/Description/<tt/atmos_save/ writes a memory block to tape. +<tag/Notes/<itemize> +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. +</itemize> <tag/Availability/cc65 <tag/See also/ <ref id="atmos_load" name="atmos_load"> @@ -1366,7 +1370,7 @@ atmos_save("hires", 0xa000, 0xc000); <tag/Declaration/<tt/int __fastcall__ atoi (const char* s);/ <tag/Description/<tt/atoi/ converts the given string into an integer. Conversion stops as soon as any invalid character is encountered. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>There is no way to detect any conversion errors. <item>The function does not check for an numerical overflow when converting. <item>The function is only available as fastcall function, so it may only be @@ -1393,7 +1397,7 @@ used in presence of a prototype. <tag/Declaration/<tt/long __fastcall__ atol (const char* s);/ <tag/Description/<tt/atol/ converts the given string into a long integer. Conversion stops as soon as any invalid character is encountered. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>There is no way to detect any conversion errors. <item>The function does not check for an numerical overflow when converting. <item>The function is only available as fastcall function, so it may only be @@ -1421,7 +1425,7 @@ used in presence of a prototype. <tag/Description/The function will set a new background color and return the old (current) one. The background color is valid for the whole text output area of the screen, not just for new text. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Background colors are system dependent. The function may have no effect on systems where the background color cannot be changed. <item>The function is only available as fastcall function, so it may only be @@ -1445,7 +1449,7 @@ used in presence of a prototype. <tag/Declaration/<tt/unsigned char __fastcall__ bordercolor (unsigned char color);/ <tag/Description/The function will set a new border color. It returns the old (current) border color. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Border colors are system dependent. The function may have no effect on systems where the border color cannot be changed. <item>The function is only available as fastcall function, so it may only @@ -1468,20 +1472,21 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void* __fastcall__ bsearch (const void* key, const void* base, size_t n, size_t size, -int (*cmp) (const void*, const void*));/ +int __fastcall__ (* cmp) (const void*, const void*));/ <tag/Description/<tt/bsearch/ searches a sorted array for a member that matches the one pointed to by <tt/key/. <tt/base/ is the address of the array, <tt/n/ is the number of elements, <tt/size/ the size of an element and <tt/cmp/ the function used to compare the members against the key. The function returns a pointer to the member found, or <tt/NULL/ if there was no match. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The contents of the array must be sorted in ascending order according to the compare function given. <item>If there are multiple members that match the key, the function will return one of the members. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. +<item>The function to which <tt/cmp/ points must have the <tt/fastcall/ calling +convention. </itemize> <tag/Availability/ISO 9899 <tag/See also/ @@ -1500,8 +1505,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ bzero (void* p, size_t count);/ <tag/Description/<tt/bzero/ fills the memory area pointed to by <tt/p/ with zero. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is non standard and therefore only available in non ANSI mode. You should use <tt/<ref id="memset" name="memset">/ instead. <item>The function is only available as fastcall function, so it may only @@ -1526,7 +1530,7 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="c128.h" name="c128.h">/ <tag/Declaration/<tt/void c64mode (void);/ <tag/Description/The function will cause the machine to reboot into C64 mode. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is specific to the C128. <item>The function will not return to the caller. </itemize> @@ -1547,8 +1551,7 @@ be used in presence of a prototype. of size <tt/size/, clears the whole block with binary zeroes and returns a pointer to it. On error (not enough memory available), <tt/calloc/ returns <tt/NULL/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>Clearing the memory may not have the expected effect on all platforms: pointers in the block may not be <tt/NULL/ and floating point variables may not be zero (0.0). In other words: The "clearing" effect of this function @@ -1581,7 +1584,7 @@ be used in presence of a prototype. gets from the current TALKer on the serial bus. In order to receive the data, the device must have previously been sent a command to TALK and a secondary address if it needs one. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -1603,7 +1606,7 @@ sent a command to TALK and a secondary address if it needs one. Device must first have been OPENed and then designated as the input channel by the CHKIN routine. When this function is called, the next byte of data available from the device is returned. Exception is the routine for the keyboard device (which is the default input device). -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -1629,7 +1632,7 @@ printed to the screen, which is the default output device. If the cassette is the current device, outputting a byte will only add it to the buffer. No actual transmission of data will occur until the 192-byte buffer is full. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -1659,7 +1662,7 @@ address as the current secondary address. If the device on the channel is a serial device, which requires a TALK command and sometimes a secondary address, function will send them over the serial bus. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -1687,7 +1690,7 @@ secondary address if necessary. This routine always buffers the current character, and defers sending it until the next byte is buffered. When the UNLISTEN command is sent, the last byte will be sent with an End or Identify (EOI). -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -1716,7 +1719,7 @@ file, its device as the current device, and its secondary address as the current secondary address. If the device on the channel uses the serial bus, and therefore requires a LISTEN command and possibly a secondary address, this information will be sent on the bus. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -1739,7 +1742,7 @@ only be used in presence of a prototype. <tag/Description/It closes all open files, by resetting the index into open files to zero and restores the default I/O devices. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -1761,7 +1764,7 @@ zero and restores the default I/O devices. <tag/Description/It is used to close a logical file after all I/O operations involving that file have been completed. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -1787,7 +1790,7 @@ the screen. Also, if the current input device was formerly a serial device, the routine sends it an UNTALK command on the serial bus, and if a serial device was formerly the current output device, the routine sends it an UNLISTEN command. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -1807,7 +1810,7 @@ sends it an UNLISTEN command. <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char cbm_k_getin (void);/ <tag/Description/Function gets a character from the current input device. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -1835,7 +1838,7 @@ VIC-20, and future models of the Commodore 64. If the I/O locations for a program are set by a call to this function, they should still remain compatible with future versions of the Commodore 64, the KERNAL and BASIC. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -1858,7 +1861,7 @@ receive data. The KERNAL routine will OR the supplied device number bit by bit to convert it to a listen address, then transmits this data as a command on the serial bus. The specified device will then go into listen mode, and be ready to accept information. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -1888,7 +1891,7 @@ loaded into memory starting at the location specified by the header. Function returns the address of the highest RAM location loaded. Before this function can be called, the KERNAL SETLFS, and SETNAM routines must be called. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -1914,7 +1917,7 @@ Input/Output operations. In order to specify the logical file number, the device number, and the secondary address if any, the cbm_k_setlfs() function must first be called. Likewise, in order to designate the filename, the cbm_k_setnam() function must be used first. After these two functions are called, cbm_k_open() is then called. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -1935,7 +1938,7 @@ functions are called, cbm_k_open() is then called. <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char cbm_k_readst (void);/ <tag/Description/This function returns the current status of the I/O devices. It is usually called after new communication to an I/O device and gives information about device status, or errors that have occurred during the I/O operation. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -1957,7 +1960,7 @@ functions are called, cbm_k_open() is then called. used before calling this function. However, a file name is not required to SAVE to device 1 (the Datassette(TM) recorder). Any attempt to save to other devices without using a file name results in an error. NOTE: Device 0 (the keyboard), device 2 (RS-232), and device 3 (the screen) cannot be SAVEd to. If the attempt is made, an error occurs, and the SAVE is stopped. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -1980,7 +1983,7 @@ only be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ cbm_k_setlfs (unsigned char LFN, unsigned char DEV, unsigned char SA);/ <tag/Description/This functions sets up the logical file by setting its number, device address, and secondary address. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2001,7 +2004,7 @@ only be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ cbm_k_setnam (const char* Name);/ <tag/Description/This function is used to set up the file name for the OPEN, SAVE, or LOAD operations. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2024,7 +2027,7 @@ only be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ cbm_k_talk (unsigned char dev);/ <tag/Description/When called, it ORs the device number with the TALK code (64, $40) and sends it on the serial bus. This commands the device to TALK. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2050,7 +2053,7 @@ bus. Only devices previously commanded to LISTEN are affected. This function is normally used after the host computer is finished sending data to external devices. Sending the UNLISTEN commands the listening devices to get off the serial bus so it can be used for other purposes. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 @@ -2070,7 +2073,7 @@ to get off the serial bus so it can be used for other purposes. <tag/Declaration/<tt/void __fastcall__ cclear (unsigned char length);/ <tag/Description/The function clears part of a line by writing <tt/length/ spaces in the current text color. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2094,7 +2097,7 @@ at a specific screen position. <tag/Description/The function moves the cursor to a specific position, and will then clear part of the line by writing <tt/length/ spaces in the current text color. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2118,7 +2121,7 @@ only be used in presence of a prototype. no character available, <tt/cgetc/ waits until the user presses a key. If the cursor is enabled by use of the <tt/cursor/ function, a blinking cursor is displayed while waiting. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>If the system supports a keyboard buffer, <tt/cgetc/ will fetch a key from this buffer and wait only if the buffer is empty. </itemize> @@ -2140,7 +2143,7 @@ from this buffer and wait only if the buffer is empty. <tag/Declaration/<tt/void __fastcall__ chline (unsigned char length);/ <tag/Description/The function outputs a horizontal line with the given length starting at the current cursor position. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The character used to draw the horizontal line is system dependent. If available, a line drawing character is used. Drawing a line that is partially off screen leads to undefined behaviour. @@ -2166,7 +2169,7 @@ used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ chlinexy (unsigned char x, unsigned char y, unsigned char length);/ <tag/Description/The function outputs a horizontal line with the given length starting at a given position. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The character used to draw the horizontal line is system dependent. If available, a line drawing character is used. Drawing a line that is partially off screen leads to undefined behaviour. @@ -2192,7 +2195,7 @@ used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ clearerr (FILE* f);/ <tag/Description/<tt/clearerr/ clears the error and end-of-file status indicators for the stream <tt/f/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2216,7 +2219,7 @@ used in presence of a prototype. time used by the program. The time is returned in implementation defined units. It can be converted to seconds by dividing by the value of the macro <tt/CLOCKS_PER_SEC/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Since the machines, cc65 generated programs run on, cannot run multiple processes, the function will actually return the time since some implementation defined point in the past. @@ -2257,7 +2260,7 @@ the upper left corner. <tag/Description/The function closes the given file descriptor. It returns zero on success and -1 on error. If an error occurs, the cause can be determined by reading the <tt/errno/ variable. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2280,7 +2283,7 @@ be used in presence of a prototype. <tag/Description/The function closes the given directory descriptor. It returns zero on success and -1 on error. If an error occurs, the cause can be determined by reading the <tt/errno/ variable. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2303,7 +2306,7 @@ be used in presence of a prototype. <tag/Description/<tt/creat/ creates a new file and returns the file descriptor associated with it. On error, -1 is returned and an error code is stored in <tt/errno/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item><tt/creat/ is identical to calling <tt/<ref id="open" name="open">/ with <tt/flags/ equal to <tt/O_WRONLY | O_CREAT | O_TRUNC/. <item>The function is only available as fastcall function, so it may only @@ -2329,7 +2332,7 @@ be used in presence of a prototype. formatted according to the format string given. The resulting string is output to the console. <tt/cprintf/ supports the same format specifiers as <tt/printf/. <!-- <tt/<ref id="printf" name="printf">/. --> -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Like all other <tt/conio/ output functions, <tt/cprintf/ distinguishes between <tt/\r/ and <tt/\n/. </itemize> @@ -2354,7 +2357,7 @@ between <tt/\r/ and <tt/\n/. <tag/Declaration/<tt/void __fastcall__ cputc (char c);/ <tag/Description/Output one character to the console at the current cursor position. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Like all other <tt/conio/ output functions, <tt/cputc/ distinguishes between <tt/\r/ and <tt/\n/. <item>The function is only available as fastcall function, so it may only @@ -2381,7 +2384,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);/ <tag/Description/<tt/cputcxy/ moves the cursor to the given x/y position on the screen and outputs one character. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Like all other <tt/conio/ output functions, <tt/cputcxy/ distinguishes between <tt/\r/ and <tt/\n/. <item>The function is only available as fastcall function, so it may only @@ -2408,7 +2411,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ cputs (const char* s);/ <tag/Description/The function outputs the given string on the console at the current cursor position. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Like all other <tt/conio/ output functions, <tt/cputs/ distinguishes between <tt/\r/ and <tt/\n/. <item>The function is only available as fastcall function, so it may only @@ -2435,7 +2438,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ cputsxy (unsigned char x, unsigned char y, const char* s);/ <tag/Description/<tt/cputsxy/ moves the cursor to the given x/y position, and outputs the string <tt/s/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Like all other <tt/conio/ output functions, <tt/cputsxy/ distinguishes between <tt/\r/ and <tt/\n/. <item>The function is only available as fastcall function, so it may only @@ -2463,7 +2466,7 @@ be used in presence of a prototype. <tag/Description/If the argument to the function is non zero, a blinking cursor will be enabled when the <tt/cgetc/ function waits for input from the keyboard. If the argument is zero, <tt/cgetc/ will wait without a blinking cursor. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2485,7 +2488,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ cvline (unsigned char length);/ <tag/Description/The function outputs a vertical line with the given length starting at the current cursor position. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The character used to draw the vertical line is system dependent. If available, a line drawing character is used. Drawing a line that is partially off screen leads to undefined behaviour. @@ -2511,7 +2514,7 @@ used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ cvlinexy (unsigned char x, unsigned char y, unsigned char length);/ <tag/Description/The function outputs a vertical line with the given length starting at a given position. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The character used to draw the vertical line is system dependent. If available, a line drawing character is used. Drawing a line that is partially off screen leads to undefined behaviour. @@ -2537,8 +2540,7 @@ used in presence of a prototype. <tag/Declaration/<tt/div_t __fastcall__ div (int numer, int denom);/ <tag/Description/<tt/div/ divides <tt/numer/ by <tt/denom/ and returns the quotient and remainder in a <tt/div_t/ structure. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2562,7 +2564,7 @@ the contents of the memory window have been changed, these changes may be lost if <tt/<ref id="em_map" name="em_map">/, <tt/<ref id="em_use" name="em_use">/, <tt/<ref id="em_copyfrom" name="em_copyfrom">/ or <tt/<ref id="em_copyto" name="em_copyto">/ are called without calling <tt/em_commit/ first. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Calling <tt/em_commit/ does not necessarily mean that changes to the memory window are discarded, it does just mean that the drivers is allowed to discard it. @@ -2591,7 +2593,7 @@ loaded. <tag/Description/Copy data from extended memory into linear memory. Source and target addresses as well as the number of bytes to transfer are specified in the <tt/em_copy/ structure that is passed as a parameter. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Calling <tt/em_copyfrom/ will invalidate the memory window, so if you made any changes to the data in the window, call <tt/<ref id="em_commit" name="em_commit">/ first, or the changes are lost. @@ -2620,7 +2622,7 @@ loaded. <tag/Description/Copy data from linear into extended memory. Source and target addresses as well as the number of bytes to transfer are specified in the <tt/em_copy/ structure that is passed as a parameter. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Calling <tt/em_copyto/ will invalidate the memory window, so if you made any changes to the data in the window, call <tt/<ref id="em_commit" name="em_commit">/ first, or the changes are lost. @@ -2649,7 +2651,7 @@ loaded. <tag/Description/The function installs an already loaded extended memory driver and returns an error code. The function may be used to install a driver linked statically to the program. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Not all drivers are able to detect if the supported hardware is really present. <item>The function is only available as fastcall function, so it may only be @@ -2675,7 +2677,7 @@ used in presence of a prototype. <tag/Description/Load an extended memory driver into memory and initialize it. The function returns an error code that tells if all this has been successful. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Not all drivers are able to detect if the supported hardware is really present. <item>The function is only available as fastcall function, so it may only be @@ -2705,7 +2707,7 @@ into a buffer. If you don't need the actual contents of the page (for example because you're going to overwrite it completely), it is better to call <tt/<ref id="em_use" name="em_use">/ instead. <tt/em_use/ will not transfer the data if it is possible to avoid that. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Calling <tt/em_map/ will invalidate the memory window, so if you made any changes to the data in the window, call <tt/<ref id="em_commit" name="em_commit">/ first, or the changes are lost. @@ -2733,7 +2735,7 @@ loaded. <tag/Declaration/<tt/unsigned em_pagecount (void);/ <tag/Description/The function returns the size of the extended memory supported by the driver in 256 byte pages. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function returns zero if no extended memory driver is loaded. <item>The function may return zero if the supported hardware was not detected. </itemize> @@ -2754,7 +2756,7 @@ by the driver in 256 byte pages. <tag/Declaration/<tt/unsigned char em_uninstall (void);/ <tag/Description/The function uninstalls an already loaded extended memory driver but doesn't remove it from memory. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>If the driver has been loaded using <tt/<ref id="em_load_driver" name="em_load_driver">/, <tt/<ref id="em_unload" name="em_unload">/ should be used instead of <tt/em_uninstall/ so the driver is also removed @@ -2779,7 +2781,7 @@ from memory. <tag/Declaration/<tt/unsigned char em_unload (void);/ <tag/Description/The function unloads a loaded extended memory driver and frees all memory allocated for the driver. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function does nothing if no driver is loaded. </itemize> <tag/Availability/cc65 @@ -2802,7 +2804,7 @@ memory and returns a pointer to the page frame. This function is similar to <tt/<ref id="em_map" name="em_map">/, but will not transfer data into the actual memory window in the assumption that the existing data is wrong or will get overwritten. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Calling <tt/em_use/ will invalidate the memory window, so if you made any changes to the data in the window, call <tt/<ref id="em_commit" name="em_commit">/ first, or the changes are lost. @@ -2834,7 +2836,7 @@ output is written and any functions registered with <tt/<ref id="atexit" name="atexit">/ are called. Common values for status are <tt/EXIT_SUCCESS/ and <tt/EXIT_FAILURE/ which are also defined in <tt/<ref id="stdlib.h" name="stdlib.h">/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>It depends on the host machine if the program return code can be @@ -2863,7 +2865,7 @@ the command line specified as second argument. Instead of an empty string, a <tt/NULL/ pointer may be passed as second parameter. On success, the function does not return. On failure, -1 is returned and <tt/errno/ contains an error code. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>On most platforms, the function needs to copy a small stub loader to @@ -2893,7 +2895,7 @@ program, it may not be able to read it. <tag/Declaration/<tt/void fast (void);/ <tag/Description/The function will switch the clock of the C128 to 2MHz. This will nearly double the speed compared to slow mode. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is specific to the C128. <item>2MHz clock will not work in 40 column mode. </itemize> @@ -2916,7 +2918,7 @@ will nearly double the speed compared to slow mode. <tag/Declaration/<tt/int __fastcall__ feof (FILE* f);/ <tag/Description/<tt/feof/ tests the end-of-file indicator ofthe stream <tt/f/, and returns a non zero value if it is set. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The indicator is set only after a read past the end of a file is attempted. <item>The function is only available as fastcall function, so it may only be @@ -2940,7 +2942,7 @@ used in presence of a prototype. <tag/Declaration/<tt/int __fastcall__ ferror (FILE* f);/ <tag/Description/<tt/ferror/ tests the error indicator of the stream <tt/f/, and returns a non zero value if it is set. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -2963,7 +2965,7 @@ used in presence of a prototype. <tag/Description/The <tt/fileno/ function returns the file handle used internally by a C stream. This file handle (an integer) can be used as a handle for the POSIX input/output functions. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>Mixing C file I/O functions and POSIX file I/O functions for the same @@ -2991,8 +2993,7 @@ file may have unpredictable results. <tt/<ref id="malloc" name="malloc">/, <tt/<ref id="calloc" name="calloc">/ or <tt/<ref id="realloc" name="realloc">/. As an exception, if the passed pointer is <tt/NULL/, no action is performed. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>Passing an already free'd block to <tt/free/ again will cause undefined behaviour and may crash your program. <item>The function is only available as fastcall function, so it may only @@ -3024,7 +3025,7 @@ be used in presence of a prototype. all supported targets. If it exists, it returns a number that identifies the operating system or machine type, the program runs on. The machine dependent header files define constants that can be used to check the return code. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function does not exist on all platforms. <item>The return codes are platform dependent. </itemize> @@ -3047,7 +3048,7 @@ returns one of the constants<itemize> <item><tt/CPU_65C02/ <item><tt/CPU_65816/ </itemize> -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Other, more exotic CPU types are not disinguished. </itemize> <tag/Availability/cc65 @@ -3067,7 +3068,7 @@ returns one of the constants<itemize> matches <tt/name/ and returns its value. The environment consists of a list of strings in the form <tt/name=value/. If there is no match, <tt/getenv/ returns <tt/NULL/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>What exactly is stored in the environment depends on the machine the program is running on. <item>The function is only available as fastcall function, so it may only @@ -3097,7 +3098,7 @@ preceeded by a '-'. found on the command line and <tt/EOF/ (-1) if there is no other option. An option argument is placed in <tt/optarg/, the index of the next element on the command line to be processed is placed in <tt/optind/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The implementation will not reorder options. A non option on the command line will terminate option processing. All remaining arguments are not recognized as options, even if the start with a '-' character. @@ -3120,7 +3121,7 @@ be used in presence of a prototype. <tag/Description/The function moves the text mode cursor to the specified X position while leaving the Y position untouched. The leftmost position on the screen has the coordinate 0. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>Invalid values for the X position (out of screen coordinates) may @@ -3147,7 +3148,7 @@ lead to undefined behaviour. <tag/Description/The function moves the text mode cursor to the specified position. The leftmost position on the screen has the X coordinate 0, the topmost line has the Y coordinate 0. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>Invalid values for any of both coordinates (out of screen positions) may @@ -3174,7 +3175,7 @@ lead to undefined behaviour. <tag/Description/The function moves the text mode cursor to the specified Y position while leaving the X position untouched. The uppermost position on the screen has the coordinate 0. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>Invalid values for the Y position (out of screen coordinates) may lead @@ -3201,7 +3202,7 @@ to undefined behaviour. <tag/Description/The function returns a non zero value if the given argument is a letter or digit. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3238,7 +3239,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Declaration/<tt/int __fastcall__ isalpha (int c);/ <tag/Description/The function returns a non zero value if the given argument is a letter. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3275,7 +3276,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Declaration/<tt/int __fastcall__ isascii (int c);/ <tag/Description/The function returns a non zero value if the given argument is in the range 0..127 (the range of valid ASCII characters) and zero if not. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3313,7 +3314,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Description/The function returns a non zero value if the given argument is a space or tab character. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3322,7 +3323,7 @@ macro. <item>When compiling without <tt/-Os/, the function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> -<tag/Availability/cc65 +<tag/Availability/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, @@ -3351,7 +3352,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Description/The function returns a non zero value if the given argument is a control character. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3388,7 +3389,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Declaration/<tt/int __fastcall__ isdigit (int c);/ <tag/Description/The function returns a non zero value if the given argument is a digit. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3427,7 +3428,7 @@ space). <tag/Description/The function returns a non zero value if the given argument is a printable character with the exception of space. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3465,7 +3466,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Description/The function returns a non zero value if the given argument is a lower case letter. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3503,7 +3504,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Description/The function returns a non zero value if the given argument is a printable character (this includes the space character). The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3542,7 +3543,7 @@ space or an alphanumeric character. <tag/Description/The function returns a non zero value if the given argument is a printable character, but not a space or anything alphanumeric. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3582,7 +3583,7 @@ is a white space character. The return value is zero if the character is anything else. The standard white space characters are: space, formfeed ('\f'), newline ('\n'), carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3620,7 +3621,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Description/The function returns a non zero value if the given argument is an upper case letter. The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3658,7 +3659,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Description/The function returns a non zero value if the given argument is a hexadecimal digit (0..9, a..f and A..F). The return value is zero if the character is anything else. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>When compiling with <tt/-Os/ the function is actually a macro. The inline sequence generated by the macro will not work correctly for values outside the range 0..255. <em/Note:/ The constant <tt/EOF/ is not part of @@ -3695,7 +3696,7 @@ fastcall function, so it may only be used in presence of a prototype. <tag/Declaration/<tt/char* __fastcall__ itoa (int val, char* buf, int radix);/ <tag/Description/<tt/itoa/ converts the integer <tt/val/ into a string using <tt/radix/ as the base. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>There are no provisions to prevent a buffer overflow. <item>If <tt/val/ contains <tt/INT_MIN/, the behaviour is undefined. <item>The function is non standard, so it is not available in strict ANSI mode. @@ -3724,7 +3725,7 @@ used in presence of a prototype. <tag/Declaration/<tt/unsigned char joy_count (void);/ <tag/Description/The function returns a the number of joysticks supported by the current joystick driver. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>A joystick driver must be loaded using <ref id="joy_load_driver" name="joy_load_driver"> before calling this function. <item>The function returns the number of joysticks supported by the driver. @@ -3749,7 +3750,7 @@ There's no way to check for the number of actually connected joysticks. <tag/Description/The function installs a driver that was already loaded into memory (or linked statically to the program). It returns an error code (<tt/JOY_ERR_OK/ in case of success). -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -3773,7 +3774,7 @@ used in presence of a prototype. <tag/Description/The function loads a driver with the given name from disk and installs it. An error code is returned, which is <tt/JOY_ERR_OK/ if the driver was successfully loaded and installed. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -3797,7 +3798,7 @@ used in presence of a prototype. <tag/Description/The function reads the status bits for a joystick. The number of the joystick is passed as parameter. The result may be examined by using one of the <tt/JOY_xxx/ macros from <ref id="joystick.h" name="joystick.h">. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>A joystick driver must be loaded using <ref id="joy_load_driver" name="joy_load_driver"> before calling this function. <item>The function is only available as fastcall function, so it may only be @@ -3823,7 +3824,7 @@ used in presence of a prototype. <tag/Description/The function uninstalls the currently installed joystick driver. It does not remove the driver from memory. The function returns an error code, which is <tt/JOY_ERR_OK/ if the driver was successfully uninstalled. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>A joystick driver must be installed using <ref id="joy_install" name="joy_install"> before calling this function. </itemize> @@ -3847,7 +3848,7 @@ name="joy_install"> before calling this function. <tag/Description/The function uninstalls the currently installed joystick driver and removes it from memory. An error code is returned, which is <tt/JOY_ERR_OK/ if the driver was successfully uninstalled. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>A joystick driver must be loaded using <ref id="joy_load_driver" name="joy_load_driver"> before calling this function. </itemize> @@ -3868,7 +3869,7 @@ name="joy_load_driver"> before calling this function. <tag/Declaration/<tt/unsigned char kbhit (void);/ <tag/Description/The function returns a value of zero if there is no character waiting to be read from the keyboard. It returns non zero otherwise. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>If the system does not support a keyboard buffer (most systems do), the function is rather useless. </itemize> @@ -3890,7 +3891,7 @@ do), the function is rather useless. <tag/Declaration/<tt/long __fastcall__ labs (long v);/ <tag/Description/<tt/labs/ returns the absolute value of the argument passed to the function. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The return value is undefined if <tt/LONG_MIN/ is passed to the function. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. @@ -3912,7 +3913,7 @@ used in presence of a prototype. <tag/Declaration/<tt/char* __fastcall__ ltoa (long val, char* buf, int radix);/ <tag/Description/<tt/itoa/ converts the long integer <tt/val/ into a string using <tt/radix/ as the base. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>There are no provisions to prevent a buffer overflow. <item>If <tt/val/ contains <tt/LONG_MIN/, the behaviour is undefined. <item>The function is non standard, so it is not available in strict ANSI mode. @@ -3941,7 +3942,7 @@ used in presence of a prototype. <tag/Declaration/<tt/struct lconv* localeconv (void);/ <tag/Description/<tt/localeconv/ returns a pointer to the current locale structure. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>cc65 supports only the "C" locale, so even after setting a new locale using <tt/<ref id="setlocale" name="setlocale">/, the structure returned will always be the same. @@ -3966,8 +3967,7 @@ data in <tt/buf/, which must have been set by a preceeding call to <tt/<ref id="setjmp" name="setjmp">/. Program execution continues as if the call to <tt/<ref id="setjmp" name="setjmp">/ has just returned the value <tt/retval/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>If the parameter <tt/retval/ is zero, the function will behave as if it was called with a value of one. <item>The function is only available as fastcall function, so it may only @@ -3991,8 +3991,7 @@ be used in presence of a prototype. <tag/Description/<tt/malloc/ allocates size bytes on the heap and returns a pointer to the allocated memory block. On error (not enough memory available), <tt/malloc/ returns <tt/NULL/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4022,7 +4021,7 @@ be used in presence of a prototype. (converted to a char) in the block of raw memory string pointed to by <tt/mem/ that is of size <tt/count/. Upon completion, the function returns a pointer to the character found, or a null pointer if the character was not found. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4045,8 +4044,7 @@ be used in presence of a prototype. pointed to by <tt/p1/ into the memory area pointed to by <tt/p2/. It returns a value that is less than zero if <tt/p1/ is less than <tt/p2/, zero if <tt/p1/ is the same as <tt/p2/, and a value greater than zero if <tt/p1/ is greater than <tt/p2/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4070,8 +4068,7 @@ be used in presence of a prototype. <tag/Description/<tt/memcpy/ copies <tt/count/ bytes from the memory area pointed to by <tt/src/ into the memory area pointed to by <tt/dest/. It returns <tt/dest/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The result is undefined if the memory areas do overlap. Use <tt/<ref id="memmove" name="memmove">/ to copy overlapping memory areas. <item>The function is only available as fastcall function, so it may only @@ -4097,8 +4094,7 @@ be used in presence of a prototype. <tag/Description/<tt/memmove/ copies <tt/count/ bytes from the memory area pointed to by <tt/src/ into the memory area pointed to by <tt/dest/. It returns <tt/dest/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>While <tt/memmove/ allows the memory areas to overlap, it has some additional overhead compared to <tt/<ref id="memcpy" name="memcpy">/. <item>The function is only available as fastcall function, so it may only @@ -4123,8 +4119,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void* __fastcall__ memset (void* p, int val, size_t count);/ <tag/Description/<tt/memset/ fills the memory area pointed to by <tt/p/ with the value <tt/val/. The function returns <tt/p/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4148,9 +4143,11 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ mod_free (void* module);/ <tag/Description/The function will free a module loaded into memory by use of the <tt/<ref id="mod_load" name="mod_load">/ function. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The pointer passed as parameter is the pointer to the module memory, not the pointer to the control structure. +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -4166,7 +4163,7 @@ not the pointer to the control structure. <descrip> <tag/Function/Load a relocatable module. <tag/Header/<tt/<ref id="modload.h" name="modload.h">/ -<tag/Declaration/<tt/unsigned char mod_load (struct mod_ctrl* ctrl);/ +<tag/Declaration/<tt/unsigned char __fastcall__ mod_load (struct mod_ctrl* ctrl);/ <tag/Description/The function will load a code module into memory and relocate it. The function will return an error code. If <tt/MLOAD_OK/ is returned, the outgoing fields in the passed <tt/mod_ctrl/ struct contain information about @@ -4179,9 +4176,11 @@ the module just loaded. Possible error codes are: <item><tt/MLOAD_ERR_FMT/ - Data format error <item><tt/MLOAD_ERR_MEM/ - Not enough memory </itemize> -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The <htmlurl url="ld65.html" name="ld65"> linker is needed to create relocatable o65 modules for use with this function. +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -4199,7 +4198,7 @@ relocatable o65 modules for use with this function. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/void __fastcall__ mouse_setbox (const struct mouse_box* box);/ <tag/Description/The function allows to set a bounding box for mouse movement. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function does not check if the mouse cursor is currently within the given rectangle. Placing the mouse cursor within the bounding box is the responsibility of the programmer. @@ -4228,7 +4227,7 @@ used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ mouse_getbox (struct mouse_box* box);/ <tag/Description/The function queries the current bounding box for mouse movement. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4270,7 +4269,7 @@ return value. code);/ <tag/Description/The function returns an error message (in english) for the error code passed parameter. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function will return "Unknown error" for invalid error codes. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. @@ -4315,7 +4314,7 @@ mouse. <tag/Declaration/<tt/void __fastcall__ mouse_info (struct mouse_info* info);/ <tag/Description/The function returns the state of the mouse buttons and the position of the mouse in the <tt/mouse_info/ structure passed as parameter. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The <tt/mouse_info/ struct is a superset of the <tt/mouse_pos/ struct, so if you just need the mouse position, call <tt/<ref id="mouse_pos" name="mouse_pos">/ instead. @@ -4346,7 +4345,7 @@ pointer. Defaults for these routines are supplied by the library, so if you can live with these defaults (which are platform specific), just pass a pointer to <tt/mouse_def_callbacks/. The function may be used to install a driver linked statically to the program. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Not all drivers are able to detect if the supported hardware is really present. <item>After installing a driver, the mouse cursor is hidden. @@ -4376,7 +4375,7 @@ different IOCTL functions, and the <tt/data/ depends on code. The function returns an error code. The purpose of this function is to allow for driver specific extensions. See the documentation for a specific mouse driver for supported ioctl calls. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Calling this function is non portable, because each driver may implement different ioctl calls (or none at all). <item>The function is only available as fastcall function, so it may only be @@ -4402,7 +4401,7 @@ function returns an error code that tells if the call has been successful. The routines needed to move or hide/show the mouse pointer. Defaults for these routines are supplied by the library, so if you can live with these defaults (which are platform specific), just pass a pointer to <tt/mouse_def_callbacks/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The driver is loaded by name, so currently you must know the type of mouse that should be supported. There is no autodetect capability. <item>Not all drivers are able to detect if the supported hardware is really @@ -4430,7 +4429,7 @@ used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ mouse_move (int x, int y);/ <tag/Description/The function updates the mouse position. If the mouse cursor is visible, it is shown at the new position. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function does not check if the new position is within the bounding box specified with <tt/<ref id="mouse_setbox" name="mouse_setbox">/. <item>The function is only available as fastcall function, so it may only be @@ -4454,7 +4453,7 @@ used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ mouse_pos (struct mouse_pos* pos);/ <tag/Description/The function returns the position of the mouse in the <tt/mouse_pos/ structure passed as parameter. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The <tt/mouse_pos/ struct is a subset of the <tt/mouse_info/ struct, so if you do also need the mouse buttons, call <tt/<ref id="mouse_info" name="mouse_info">/ instead. @@ -4498,7 +4497,7 @@ that is shared between <tt/<ref id="mouse_hide" name="mouse_hide">/ and <tag/Declaration/<tt/unsigned char mouse_uninstall (void);/ <tag/Description/The function uninstalls an already loaded mouse driver but don't removes it from memory. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>If the driver has been loaded using <tt/<ref id="mouse_load_driver" name="mouse_load_driver">/, <tt/<ref id="mouse_unload" name="mouse_unload">/ should be used instead of <tt/mouse_uninstall/ so the driver is also removed @@ -4520,10 +4519,10 @@ from memory. <descrip> <tag/Function/Unload a mouse driver. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ -<tag/Declaration/<tt/unsigned char __fastcall__ mouse_unload (void);/ +<tag/Declaration/<tt/unsigned char mouse_unload (void);/ <tag/Description/The function unloads a loaded mouse driver and frees all memory allocated for the driver. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function does nothing if no driver is loaded. </itemize> <tag/Availability/cc65 @@ -4545,7 +4544,7 @@ memory allocated for the driver. <tag/Declaration/<tt/size_t offsetof (type, member);/ <tag/Description/<tt/offsetof/ calculates the address offset of a <tt/struct/ or <tt/union/ member. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/ISO 9899 @@ -4564,7 +4563,7 @@ or <tt/union/ member. <tag/Description/<tt/open/ opens a file and returns the file descriptor associated with it. On error, -1 is returned and an error code is stored in <tt/errno/. Several flags may be passed to <tt/open/ that change the behaviour. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>POSIX specifies an additional <tt/mode/ argument that may be passed to open, which is used as the permission mask when a new file is created. While cc65 allows to pass this argument, it is ignored. @@ -4588,7 +4587,7 @@ cc65 allows to pass this argument, it is ignored. <tag/Description/<tt/opendir/ opens a directory and returns the direcory descriptor associated with it. On error, NULL is returned and an error code is stored in <tt/errno/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4611,8 +4610,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/unsigned char __fastcall__ peekbsys (unsigned addr);/ <tag/Description/<tt/peekbsys/ reads one byte from the given address in the system bank (bank 15) of the CBM PET-II machines and returns it. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>This function may be a macro depending on the compiler options. The @@ -4642,8 +4640,7 @@ actual function is accessible by #undef'ing the macro. system bank (bank 15) of the CBM PET-II machines and returns it. Following the usual 6502 conventions, the low byte is read from <tt/addr/, and the high byte is read from <tt/addr+1/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The order in which the two bytes are read is undefined. @@ -4672,8 +4669,7 @@ is not <tt/NULL/ and not an empty string, it is printed followed by a colon and a blank. Then the error message for the current contents of <tt/errno/ is printed followed by a newline. The message output is the same as returned by <tt/<ref id="strerror" name="strerror">/ with an argument of <tt/errno/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4696,8 +4692,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ pokebsys (unsigned addr, unsigned char val);/ <tag/Description/<tt/pokebsys/ writes one byte to the given address in the system bank (bank 15) of the CBM PET-II machines. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4725,8 +4720,7 @@ be used in presence of a prototype. system bank (bank 15) of the CBM PET-II machines. Following the usual 6502 conventions, the low byte of <tt/val/ is written to <tt/addr/, and the high byte is written to <tt/addr+1/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The order in which the two bytes are written is undefined. @@ -4750,17 +4744,18 @@ be used in presence of a prototype. <tag/Function/Sort an array. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void __fastcall__ qsort (void* base, size_t count, -size_t size, int (*compare) (const void*, const void*));/ +size_t size, int __fastcall__ (* compare) (const void*, const void*));/ <tag/Description/<tt/qsort/ sorts an array according to a given compare function <tt/compare/. <tt/base/ is the address of the array, <tt/count/ is the number of elements, <tt/size/ the size of an element and <tt/compare/ the function used to compare the members. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>If there are multiple members with the same key, the order after calling the function is undefined. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. +<item>The function to which <tt/compare/ points must have the <tt/fastcall/ +calling convention. </itemize> <tag/Availability/ISO 9899 <tag/See also/ @@ -4782,7 +4777,7 @@ program has installed a signal handler for the signal, this signal handler will be executed. If no handler has been installed, the default action for the raised signal will be taken. The function returns zero on success, nonzero otherwise. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -4804,7 +4799,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/int rand (void);/ <tag/Description/The function returns a pseudo random number between 0 and <tt/RAND_MAX/ (exclusive). -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Without using <tt><ref id="srand" name="srand"></tt>, always the same flow of numbers is generated. <item>On startup, the function behaves as if <ref id="srand" name="srand"> @@ -4831,7 +4826,7 @@ stream pointed to by <tt/dir/. It stores the data in a <tt/dirent/ structure and returns a pointer to it. If the end of directory is reached, or an error occurs, NULL is returned. In case of errors, an error code is stored into <tt/errno/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The returned pointer may point to a statically allocated instance of @@ -4870,8 +4865,7 @@ by <tt/block/ to <tt/size/ bytes. If <tt/block/ is <tt/NULL/, <tt/realloc/ behaves as if <tt/malloc/ had been called. If <tt/size/ is zero, <tt/realloc/ behaves as if <tt/free/ had been called. On error (not enough memory available), <tt/realloc/ returns <tt/NULL/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The part of the memory block that is returned will have its contents unchanged. <item>This function is somewhat dangerous to use. Be careful to save the @@ -4907,8 +4901,7 @@ be used in presence of a prototype. <tag/Description/<tt/remove/ deletes the file with the given name. On success, zero is returned. On error, -1 is returned and <tt/errno/ is set to an error code describing the reason for the failure. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>This function is not available on all cc65 targets (depends on the availability of file I/O). <item>The function is only available as fastcall function, so it may only @@ -4944,8 +4937,7 @@ if (remove (FILENAME) == 0) { <tag/Description/<tt/rename/ renames a file (gives it a new name). On success, zero is returned. On error, -1 is returned and <tt/errno/ is set to an error code describing the reason for the failure. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>This function is not available on all cc65 targets (depends on the capabilities of the storage devices). <item>The function is only available as fastcall function, so it may only @@ -4980,11 +4972,9 @@ if (rename (OLDNAME, NEWNAME) == 0) { <tag/Declaration/<tt/void reset_brk (void);/ <tag/Description/<tt/reset_brk/ resets the break vector to the value it had before a call to <tt/set_brk/. -<tag/Limits/ -<itemize> -<item>Since <tt/<ref id="set_brk" name="set_brk">/ installs an exit handler, -it is not strictly necessary to call this function as part of the cleanup when -the program ends. +<tag/Notes/<itemize> +<item>The break vector is reset on program termination, so it's not strictly +necessary to call this function as a part of your clean-up when exitting the program. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -5004,10 +4994,9 @@ the program ends. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <tag/Declaration/<tt/void reset_irq (void);/ <tag/Description/<tt/reset_irq/ resets the C level interrupt request vector. -<tag/Limits/ -<itemize> -<item>The original IRQ vector is restored on program termination even without -calling this function. +<tag/Notes/<itemize> +<item>The interrupt vector is reset on program termination, so it's not strictly +necessary to call this function as a part of your clean-up when exitting the program. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -5029,7 +5018,7 @@ calling this function. <tag/Description/If the argument is non zero, the function enables reverse character display. If the argument is zero, reverse character display is switched off. The old value of the setting is returned. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function may not be supported by the hardware, in which case the call is ignored. <item>The function is only available as fastcall function, so it may only @@ -5052,7 +5041,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ rewinddir (DIR* dir);/ <tag/Description/<tt/rewinddir/ sets the position of the directory stream pointed to by <tt/dir/ to the start of the directory. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5073,7 +5062,7 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/void __fastcall__ screensize (unsigned char* x, unsigned char* y);/ <tag/Description/The function returns the dimensions of the text mode screen. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5099,7 +5088,7 @@ be used in presence of a prototype. <tag/Description/<tt/seekdir/ sets the position of the directory stream pointed to by <tt/dir/ to the value given in <tt/offset/, which should be a value returned by <tt/<ref id="telldir" name="telldir">/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5153,7 +5142,7 @@ static void initialize(){ <tag/Description/Get a character from the serial port. If no characters are available, the function will return SER_ERR_NO_DATA, so this is not a fatal error. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5180,7 +5169,7 @@ while (ser_get(&ch) == SER_ERR_NO_DATA) <tag/Description/The function installs a driver that was already loaded into memory (or linked statically to the program). It returns an error code (<tt/SER_ERR_OK/ in case of success). -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5206,7 +5195,7 @@ ser_install(lynx_comlynx); //Include the driver statically instead of loading it <tag/Description/Some platforms have extra serial functions that are not supported by standard serial driver functions. You can extend the driver to support this extra functionality bt using ser_ioctl functions. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>These functions are not easily portable to other cc65 platforms. @@ -5226,7 +5215,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/unsigned char __fastcall__ ser_load_driver (const char *name);/ <tag/Description/Load and install the driver by name. Will just load the driver and check if loading was successful. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5245,7 +5234,7 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ ser_open (const struct ser_params* params);/ <tag/Description/Open the port by setting the port parameters and enable interrupts. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5282,7 +5271,7 @@ static void initialize(){ <tag/Description/Send a character via the serial port. There is a transmit buffer, but transmitting is not done via interrupt. The function returns SER_ERR_OVERFLOW if there is no space left in the transmit buffer. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5304,7 +5293,7 @@ ser_put('A'); <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ ser_status (unsigned char* status);/ <tag/Description/Return the serial port status. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5355,8 +5344,7 @@ be used in presence of a prototype. program code by letting the vector point to a user written C function. The runtime library installs a small stub that saves the registers into global variables that may be accessed (and changed) by the break handler. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The stub saves the zero page registers used by the C runtime and switches @@ -5367,9 +5355,9 @@ function called from it. <item>The <tt/brk_pc/ variable points to the <tt/BRK/ instruction. If you want the continue with the interrupted code, you have to adjust <tt/brk_pc/, otherwise the <tt/BRK/ instruction will get executed over and over again. -<item>Since <tt/set_brk/ installs an exit handler, it is not strictly necessary -to call <tt/<ref id="reset_brk" name="reset_brk">/ as part of the cleanup when -the program terminates. +<item>The break vector is reset on program termination, so it's not strictly +necessary to call <tt/<ref id="reset_brk" name="reset_brk">/ as a part of your +clean-up when exitting the program. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -5396,8 +5384,7 @@ was set up to handle a "private", "exclusive" interrupt request source it must return the value <tt/IRQ_HANDLED/ if and only if it has verified that the current interrupt request actually stems from that source. In all other cases it must return the value <tt/IRQ_NOT_HANDLED/. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The stub saves the registers and zero page locations used by the C runtime @@ -5406,9 +5393,9 @@ runtime overhead, but it it is safe to execute C code, even if other C code was interrupted. Be careful however not to call C library functions, and do not enable stack checks for the handler function or any other function called from it. -<item>The interrupt vector is reset on function termination, so it's not -strictly necessary to call <tt/<ref id="reset_irq" name="reset_irq">/ as part -of the cleanup when the program terminates. +<item>The interrupt vector is reset on program termination, so it's not strictly +necessary to call <tt/<ref id="reset_irq" name="reset_irq">/ as a part of your +clean-up when exitting the program. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -5430,8 +5417,7 @@ of the cleanup when the program terminates. <tag/Description/The <tt/setjmp/ function saves the current context in <tt/buf/ for subsequent use by the <tt/<ref id="longjmp" name="longjmp">/ function and returns zero. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item><tt/setjmp/ is actually a macro as required by the ISO standard. @@ -5453,8 +5439,7 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="locale.h" name="locale.h">/ <tag/Declaration/<tt/char* __fastcall__ setlocale (int category, const char* locale);/ <tag/Description/<tt/setlocale/ sets or queries the program's locale. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>cc65 supports only the "C" locale, so calling this function to set a @@ -5482,7 +5467,7 @@ handler may either be a user supplied function, or one of the predefined signal handlers <tt/SIG_IGN/ or <tt/SIG_DFL/. The function returns the previous value if the signal , or the special function vector SIG_ERR in case of an error. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5504,7 +5489,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void __fastcall__ sleep (unsigned seconds);/ <tag/Description/The function will return after the specified number of seconds have elapsed. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5523,7 +5508,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void slow (void);/ <tag/Description/The function will switch the clock of the C128 to 1MHz. This will halve the speed compared to fast mode. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is specific to the C128. </itemize> <tag/Availability/C128 @@ -5546,7 +5531,7 @@ will halve the speed compared to fast mode. <tag/Description/The function initializes the random number generator using the given seed. On program startup, the generator behaves as if <tt/srand/ has been called with an argument of 1. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5570,7 +5555,7 @@ be used in presence of a prototype. as parameters without case sensitivity. It returns a value that is less than zero if <tt/s1/ is less than <tt/s2/, zero if <tt/s1/ is the same as <tt/s2/, and a value greater than zero if <tt/s1/ is greater than <tt/s2/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function is not available in strict ANSI mode. @@ -5598,7 +5583,7 @@ be used in presence of a prototype. pointed to by s2 (including the terminating null byte) to the end of the string pointed to by s1. The initial byte of s2 overwrites the null byte at the end of s1. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>If copying takes place between objects that overlap, the behaviour @@ -5625,7 +5610,7 @@ is undefined. (converted to a char) in the string pointed to by <tt/s/. The terminating null byte is considered to be part of the string. Upon completion, the function returns a pointer to the byte, or a null pointer if the byte was not found. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5649,7 +5634,7 @@ be used in presence of a prototype. parameters. It returns a value that is less than zero if <tt/s1/ is less than <tt/s2/, zero if <tt/s1/ is the same as <tt/s2/, and a value greater than zero if <tt/s1/ is greater than <tt/s2/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5677,7 +5662,7 @@ parameters, according to the collating sequence set by <tt/<ref id="setlocale" name="setlocale">/. It returns a value that is less than zero if <tt/s1/ is less than <tt/s2/, zero if <tt/s1/ is the same as <tt/s2/, and a value greater than zero if <tt/s1/ is greater than <tt/s2/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5704,7 +5689,7 @@ be used in presence of a prototype. <tag/Description/The <tt/strcpy/ function copies the string pointed to by <tt/s2/ (including the terminating null byte) into the array pointed to by <tt/s1/. The function will always return <tt/s1/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>If copying takes place between objects that overlap, the behaviour @@ -5737,7 +5722,7 @@ strcpy (hello, "Hello world!\n"); <tag/Description/The <tt/strcspn/ function computes and returns the length of the substring pointed to by <tt/s/ which does <em>not</em> consist of characters contained in the string <tt/set/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5763,7 +5748,7 @@ be used in presence of a prototype. to hold a copy of <tt/s/ including the terminating zero. If the allocation fails, <tt/NULL/ is returned, otherwise <tt/s/ is copied into the allocated memory block, and a pointer to the block is returned. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>It is up to the caller to free the allocated memory block. @@ -5788,7 +5773,7 @@ be used in presence of a prototype. given error code. If an invalid error code is passed, the string "Unknown error" is returned, and <tt/errno/ is set to <tt/EINVAL/. In all other cases, <tt/errno/ is left untouched. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>While the return type of the function is a <tt/char*/, the returned @@ -5813,7 +5798,7 @@ string must not be modified by the caller! parameters without case sensitivity. It returns a value that is less than zero if <tt/s1/ is less than <tt/s2/, zero if <tt/s1/ is the same as <tt/s2/, and a value greater than zero if <tt/s1/ is greater than <tt/s2/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function is not available in strict ANSI mode. @@ -5839,7 +5824,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/size_t __fastcall__ strlen (const char* s);/ <tag/Description/The <tt/strlen/ function computes the number of bytes in the string to which s points, not including the terminating null byte. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>When compiling with <tt/-Os/ (inline known standard functions), the @@ -5862,7 +5847,7 @@ function does not work correctly for strings with more than 255 characters. <tag/Declaration/<tt/char* __fastcall__ strlower (char* s);/ <tag/Description/The <tt/strlower/ function will apply the <tt/tolower/ function to each character of a string. The function will always return <tt/s/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function prototype is unavailable when compiling in strict ANSI mode. @@ -5895,7 +5880,7 @@ See <tt/strlower/. of the string pointed to by s2 to the end of the string pointed to by s1. The terminating null character at the end of s1 is overwritten. A terminating null character is appended to the result, even if not all of s2 is appended to s1. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>If copying takes place between objects that overlap, the behaviour @@ -5923,7 +5908,7 @@ characters of the two strings passed as parameters. It returns a value that is less than zero if the first <tt/count/ characters of <tt/s1/ are less than <tt/s2/, zero if they are identical, and a value greater than zero they are greater. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -5951,7 +5936,7 @@ the array pointed to by <tt/s2/ to the array pointed to by <tt/s1/. If the array pointed to by <tt/s2/ is a string that is shorter than <tt/n/ bytes, null bytes are appended to the copy in the array pointed to by <tt/s1/, until <tt/n/ bytes are written. The function always will return <tt/s1/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is available only as a fastcall function; so, it may be used only in the presence of a prototype. <item>If there is no null byte in the first <tt/n/ bytes of the array pointed @@ -5991,7 +5976,7 @@ string <tt/s2/. Tokens inside quotation marks may contain characters from <tt/s2 pointer to the first token in the string <tt/s1/. The following calls must pass a <tt/NULL/ pointer as <tt/s1/, in order to get the next token in the string. Different sets of delimiters may be used for the subsequent calls to <tt/strqtok()/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is available only as a fastcall function; so, it may be used only in the presence of a prototype. <item><tt/strqtok()/ will modify the string <tt/s1/. @@ -6020,7 +6005,7 @@ a second <tt/s1/ string before it finishes the first one. (converted to a char) in the string pointed to by <tt/s/. The terminating null byte is considered to be part of the string. Upon completion, the function returns a pointer to the byte, or a null pointer if the byte was not found. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6042,7 +6027,7 @@ be used in presence of a prototype. <tag/Description/The <tt/strspn/ function computes and returns the length of the substring pointed to by <tt/s/ which does consist only of characters contained in the string <tt/set/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6065,7 +6050,7 @@ be used in presence of a prototype. <tag/Description/<tt/strstr/ searches for the first occurance of the string <tt/substr/ within <tt/str/. If found, it returns a pointer to the copy, otherwise it returns <tt/NULL/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6091,7 +6076,7 @@ to <tt/strtok()/ will return a pointer to the first token in the string <tt/s1/. The following calls must pass a <tt/NULL/ pointer as <tt/s1/, in order to get the next token in the string. Different sets of delimiters may be used for the subsequent calls to <tt/strtok()/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item><tt/strtok()/ will modify the string <tt/s1/. @@ -6123,7 +6108,7 @@ transformed strings, it returns a value greater than, equal to, or less than zero, corresponding to the result of the <tt/strcoll/ function applied to the same two original strings. No more than n characters are placed into the resulting array pointed to by s1, including the terminating null character. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item><tt/s1/ and <tt/s2/ must not point to the same memory area, otherwise the behaviour is undefined. <item>If <tt/n/ is zero, <tt/s1/ may be a NULL pointer. @@ -6151,7 +6136,7 @@ just copy s2 to s1 using <tt><ref id="strncpy" name="strncpy"></tt>. <tag/Declaration/<tt/char* __fastcall__ strupper (char* s);/ <tag/Description/The <tt/strupper/ function will apply the <tt/toupper/ function to each character of a string. The function will always return <tt/s/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function prototype is unavailable when compiling in strict ANSI mode. @@ -6183,7 +6168,7 @@ See <tt/strupper/. <tag/Description/<tt/telldir/ returns the current position of a directory stream. The return value may be used in subsequent calls to <tt/<ref id="seekdir" name="seekdir">/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6206,7 +6191,7 @@ be used in presence of a prototype. <tag/Description/The function will set a new text color. It returns the old (current) text color. Text output using any <tt/conio.h/ function will use the color set by this function. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Text colors are system dependent. The function may have no effect on systems where the text color cannot be changed. <item>The function is only available as fastcall function, so it may only @@ -6233,7 +6218,7 @@ unsigned char rx, unsigned char ry, unsigned sa, unsigned ea);/ radii rx/ry using the current drawing color. The arc covers the angle between sa and ea (startangle and endangle), which must be in the range 0..360. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function behaves unexpectedly or may crash if the angles are out @@ -6265,7 +6250,7 @@ color. <tag/Declaration/<tt/void __fastcall__ tgi_bar (int x1, int y1, int x2, int y2);/ <tag/Description/The function fills a rectangle on the drawpage with the current color. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6287,7 +6272,7 @@ tgi_bar(10, 10, 100, 60); <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_circle (int x, int y, unsigned char radius);/ <tag/Description/The function draws a circle in the current color. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6347,7 +6332,7 @@ Will NOT uninstall or unload the driver! <tag/Declaration/<tt/void __fastcall__ tgi_ellipse (int x, int y, unsigned char rx, unsigned char ry);/ <tag/Description/The function draws an ellipse at position x/y with radii rx and ry, using the current drawing color. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6374,7 +6359,7 @@ tgi_ellipse (50, 40, 40, 20); <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_free_vectorfont (const tgi_vectorfont* font);/ <tag/Description/Free a vector font that was previously loaded into memory. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6397,7 +6382,7 @@ driver and display as an 8.8 fixed point value. It may be used to correct geometric shapes so they look correct on the display. As an example, a circle with a radius of 100 pixels may look elliptic on some driver/display combinations if the aspect ratio is not 1.00. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The aspect ratio is encoded in the TGI driver which assumes a "standard" monitor for the given platform. The aspect ratio may be wrong if another monitor is used. @@ -6501,7 +6486,7 @@ This will also clear the error. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/const char* __fastcall__ tgi_geterrormsg (unsigned char code);/ <tag/Description/Get an error message describing the error. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6597,7 +6582,7 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ tgi_getpixel (int x, int y);/ <tag/Description/Get the color of a pixel from the viewpage. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6648,7 +6633,7 @@ This is same as tgi_maxy()+1. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_gotoxy (int x, int y);/ <tag/Description/Set graphics cursor at x, y. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6668,7 +6653,7 @@ be used in presence of a prototype. <tag/Declaration/<tt/void tgi_init (void);/ <tag/Description/The tgi_init function will set the default palette to the hardware. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item><tt/tgi_init/ will not clear the screen. This allows switching between text and graphics mode on platforms that have separate memory areas for the screens. If you want the screen cleared, call <tt/<ref id="tgi_clear" @@ -6694,7 +6679,7 @@ tgi_init(); //Set up the default palette and clear the screen. <tag/Description/The function installs a driver that was already loaded into memory (or linked statically to the program). It returns an error code (<tt/TGI_ERR_OK/ in case of success). -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6722,7 +6707,7 @@ tgi_init(); //Set up the default palette and clear the screen. Install a vector font for use. More than one vector font can be loaded, but only one can be active. This function is used to tell which one. Call with a NULL pointer to uninstall the currently installed font. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6745,7 +6730,7 @@ used in presence of a prototype. <tag/Description/Some platforms have extra display hardware that is not supported by standard tgi functions. You can extend the driver to support this extra hardware using tgi_ioctl functions. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>These functions are not easily portable to other cc65 platforms. @@ -6780,7 +6765,7 @@ The graphics cursor will be set to x2/y2 by this call. <tag/Declaration/<tt/void __fastcall__ tgi_line (int x1, int y1, int x2, int y2);/ <tag/Description/Draw a line in the current drawing color. The graphics cursor will be set to x2/y2 by this call. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6801,7 +6786,7 @@ cursor to the new end point. The graphics cursor will be updated to x2/y2. <tag/Declaration/<tt/void __fastcall__ tgi_lineto (int x2, int y2);/ <tag/Description/Draw a line in the current drawing color from the graphics cursor to the new end point. The graphics cursor will be updated to x2/y2. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6822,7 +6807,7 @@ be used in presence of a prototype. <tag/Description/Load and install the driver by name. Will just load the driver and check if loading was successful. Will not switch to graphics mode. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6844,7 +6829,7 @@ be used in presence of a prototype. Load a vector font into memory and return it. In case of errors, NULL is returned and an error is set, which can be retrieved using tgi_geterror. To use the font, it has to be installed using tgi_install_vectorfont. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6867,7 +6852,7 @@ The graphics cursor is moved to the end of the text. <tag/Declaration/<tt/void __fastcall__ tgi_outtext (const char* s);/ <tag/Description/Output text at the current graphics cursor position. The graphics cursor is moved to the end of the text. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6888,7 +6873,7 @@ The graphics cursor is moved to the end of the text. <tag/Declaration/<tt/void __fastcall__ tgi_outtextxy (int x, int y, const char* s);/ <tag/Description/Output text at the given cursor position. The graphics cursor is moved to the end of the text. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6911,7 +6896,7 @@ unsigned char rx, unsigned char ry, unsigned sa, unsigned ea);/ and radii rx/ry using the current drawing color. The pie slice covers the angle between sa and ea (startangle and endangle), which must be in the range 0..360. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function behaves unexpectedly or may crash if the angles are out @@ -6943,7 +6928,7 @@ driver and display. The argument is an 8.8 fixed point value. The aspect ratio may be used to correct geometric shapes so they look correct on a given display. As an example, a circle with a radius of 100 pixels may look elliptic on some driver/display combinations if the aspect ratio is not 1.00. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The aspect ratio is encoded in the TGI driver which assumes a "standard" monitor for the given platform. The aspect ratio may be wrong if another monitor is used. @@ -6954,6 +6939,8 @@ ratio for a loaded driver. The value is not reset by <ref id="tgi_init" name="tgi_init">, so if a driver is linked statically to an application, switching into and out of graphics mode will not restore the original aspect ratio. +<item>The function is available only as a fastcall function; so, it may be used +only in the presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ @@ -6971,7 +6958,7 @@ ratio. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_setcolor (unsigned char color);/ <tag/Description/Set color to be used in future draw operations. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -6997,7 +6984,7 @@ tgi_bar(10,10,20,20); is seen immediately as it is drawn. For double buffered games you can set the drawpage to a different page than the viewpage. This lets you draw the next screen in the background and when the screen is ready you display it. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7025,7 +7012,7 @@ Palette is a pointer to as many entries as there are colors. <tag/Declaration/<tt/void __fastcall__ tgi_setpalette (const unsigned char* palette);/ <tag/Description/Set the palette (not available with all drivers/hardware). Palette is a pointer to as many entries as there are colors. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7043,7 +7030,7 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_setpixel (int x, int y);/ <tag/Description/Plot a pixel on the drawpage with the current color. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7064,7 +7051,7 @@ be used in presence of a prototype. is seen immediately as it is drawn. For double buffered games you can set the drawpage to a different page than the viewpage. This lets you draw the next screen in the background and when the screen is ready you display it. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7092,7 +7079,7 @@ the current text style. <tag/Declaration/<tt/unsigned __fastcall__ tgi_gettextheight (const char* s);/ <tag/Description/Calculate the height of the text in pixels according to the current text style. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7112,7 +7099,7 @@ be used in presence of a prototype. <tag/Description/ Set the scaling for text output. The scaling factors for width and height are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7131,7 +7118,7 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_settextstyle (unsigned char magx, unsigned char magy, unsigned char dir, unsigned char font);/ <tag/Description/Set the style for text output. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7150,7 +7137,7 @@ be used in presence of a prototype. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned __fastcall__ tgi_gettextwidth (const char* s);/ <tag/Description/Calculate the width of the text in pixels according to the current text style. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7203,7 +7190,7 @@ Will call tgi_done if necessary. measured in seconds. If the pointer <tt/t/ is not <tt/NULL/, the function result will also be stored there. If no time is available, <tt/(time_t)-1/ is returned and <tt/errno/ is set to <tt/ENOSYS/. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>Many platforms supported by cc65 do not have a realtime clock, so the @@ -7227,7 +7214,7 @@ returned value may not be valid. <tag/Description/Toggle between 40 and 80 column mode. The settings for the old mode (cursor position, color and so on) are saved and restored together with the mode. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is specific to the C128. <item>This function is deprecated. Please use <ref id="videomode" name="videomode"> instead! @@ -7251,7 +7238,7 @@ name="videomode"> instead! <tag/Declaration/<tt/int __fastcall__ tolower (int c);/ <tag/Description/The function returns the given character converted to lower case. If the given character is not a letter, it is returned unchanged. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7274,7 +7261,7 @@ only be used in presence of a prototype. <tag/Declaration/<tt/int __fastcall__ toupper (int c);/ <tag/Description/The function returns the given character converted to upper case. If the given character is not a letter, it is returned unchanged. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> @@ -7297,7 +7284,7 @@ only be used in presence of a prototype. <tag/Declaration/<tt/char* __fastcall__ ultoa (unsigned long val, char* buf, int radix);/ <tag/Description/<tt/itoa/ converts the unsigned long integer <tt/val/ into a string using <tt/radix/ as the base. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>There are no provisions to prevent a buffer overflow. <item>The function is non standard, so it is not available in strict ANSI mode. You should probably use <tt/sprintf/ instead. @@ -7326,8 +7313,7 @@ used in presence of a prototype. <tag/Description/<tt/unlink/ deletes the file with the given name. On success, zero is returned. On error, -1 is returned and <tt/errno/ is set to an error code describing the reason for the failure. -<tag/Limits/ -<itemize> +<tag/Notes/<itemize> <item>The use of this function is discouraged. Please use <tt/<ref id="remove" name="remove">/ instead, which is a native ANSI C function and does the same. <item>This function is not available on all cc65 targets (depends on the @@ -7367,7 +7353,7 @@ if (unlink (FILENAME) == 0) { <tag/Declaration/<tt/char* __fastcall__ utoa (unsigned val, char* buf, int radix);/ <tag/Description/<tt/itoa/ converts the unsigned integer <tt/val/ into a string using <tt/radix/ as the base. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>There are no provisions to prevent a buffer overflow. <item>The function is non standard, so it is not available in strict ANSI mode. You should probably use <tt/sprintf/ instead. @@ -7397,7 +7383,7 @@ used in presence of a prototype. text where necessary and formatted according to the format string given. The resulting string is output to the console. <tt/vcprintf/ supports the same format specifiers as <tt/vprintf/. <!-- <tt/<ref id="vprintf" name="vprintf">/. --> -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>Like all other <tt/conio/ output functions, <tt/vcprintf/ distinguishes between <tt/\r/ and <tt/\n/. <item>The function is only available as fastcall function, so it may only be @@ -7426,7 +7412,7 @@ used in presence of a prototype. <tag/Description/Switch to 40 or 80 column mode depending on the argument. If the requested mode is already active, nothing happens. The old mode is returned from the call. -<tag/Limits/<itemize> +<tag/Notes/<itemize> <item>The function is specific to the C128 and enhanced Apple //e. <item>This function replaces <ref id="toggle_videomode" name="toggle_videomode">. diff --git a/doc/index.sgml b/doc/index.sgml index 7de8b26ce..b6ef06ef9 100644 --- a/doc/index.sgml +++ b/doc/index.sgml @@ -18,6 +18,9 @@ <tag><htmlurl url="cc65.html" name="cc65.html"></tag> Describes the cc65 C compiler. + <tag><htmlurl url="chrcvt.html" name="chrcvt.html"></tag> + Describes the vector font converter. + <tag><htmlurl url="cl65.html" name="cl65.html"></tag> Describes the cl65 compile & link utility. @@ -36,6 +39,9 @@ <tag><htmlurl url="od65.html" name="od65.html"></tag> Describes the od65 object-file analyzer. + <tag><htmlurl url="sim65.html" name="sim65.html"></tag> + Describes the 6502 and 65C02 simulator. + <tag><htmlurl url="sp65.html" name="sp65.html"></tag> Describes the sprite and bitmap utility. @@ -83,7 +89,7 @@ An overview over the cc65 runtime and C libraries. <tag><htmlurl url="smc.html" name="smc.html"></tag> - Describes Christian Krügers macro package for writing self modifying + Describes Christian Krüger's macro package for writing self modifying assembler code. <tag><url name="6502 Binary Relocation Format document" @@ -134,6 +140,12 @@ <tag><htmlurl url="nes.html" name="nes.html"></tag> Topics specific to the Nintendo Entertainment System. + <tag><htmlurl url="osi.html" name="osi.html"></tag> + Topics specific to the Ohio Scientific machines. + + <tag><htmlurl url="pce.html" name="pce.html"></tag> + Topics specific to NEC PC-Engine (TurboGrafx) Console. + <tag><htmlurl url="pet.html" name="pet.html"></tag> Topics specific to the Commodore PET machines. @@ -141,7 +153,7 @@ Topics specific to the Commodore Plus/4. <tag><htmlurl url="supervision.html" name="supervision.html"></tag> - Topics specific to the Supervision Console. + Topics specific to the Watara Supervision Console. <tag><htmlurl url="vic20.html" name="vic20.html"></tag> Topics specific to the Commodore VIC20. @@ -150,4 +162,3 @@ </article> - diff --git a/doc/intro.sgml b/doc/intro.sgml index 02c5c83d5..d92fd1d20 100644 --- a/doc/intro.sgml +++ b/doc/intro.sgml @@ -6,8 +6,9 @@ <author> <url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:cbmnut@hushmail.com" name="CbmNut">,<newline> -<url url="mailto:greg.king5@verizon.net" name="Greg King"> -<date>2014-4-24 +<url url="mailto:greg.king5@verizon.net" name="Greg King">,<newline> +<url url="mailto:stephan.muehlstrasser@web.de" name="Stephan Mühlstrasser"> +<date>2015-03-07 <abstract> How to use the cc65 C language system -- an introduction. @@ -342,8 +343,8 @@ Available at <url url="http://code.google.com/p/oriculator/">: Emulates Oric-1 and Atmos computers, with sound, disk images, -scanline-exact NTSC/PAL video, and movie export. Includes monitor. -Fortunately for all SDL platforms. You will just need the emulator, all +scanline-exact NTSC/PAL video, and movie export. Includes a monitor. +Fortunately, for all SDL platforms. You will need just the emulator; all ROMs are supplied. Compile the tutorial with @@ -353,8 +354,11 @@ cl65 -O -t atmos hello.c text.s -o hello.tap </verb></tscreen> Start the emulator, choose <bf/F1/ and <bf/Insert tape.../, and point to -the "<bf/hello.tap/" executable. The file has an auto start header meant to -be loaded directly from tape. +the "<bf/hello.tap/" executable. After it has finished loading, type + +<tscreen><verb> +RUN +</verb></tscreen> On a real Atmos, you would need a tape drive. Turn on the computer, type @@ -363,7 +367,11 @@ Turn on the computer, type CLOAD"" </verb></tscreen> -at the BASIC prompt. +at the BASIC prompt. After it has finished loading, type + +<tscreen><verb> +RUN +</verb></tscreen> The emulation, also, supports that method. @@ -514,6 +522,127 @@ The output is shown in a GEOS dialog box; click <bf/OK/ when you have finished reading it. +<sect1>Ohio Scientific Challenger 1P<p> +The <tt/osic1p/ runtime library returns to the boot prompt when the main() +program exits. Therefore, the C file in the tutorial must be modified +slightly, in order to see the results on the screen. Otherwise, the program +would print the text string, and then jump to the boot prompt, making it +impossible to see the results of running the tutorial program. + +In addition to that, the <tt/osic1p/ target does not yet have support for stdio +functions. Only the functions from the conio library are available. + +Therefore, modify the "<tt/hello.c/" source file, as follows: + +<tscreen><code> +#include <conio.h> +#include <stdlib.h> + +extern const char text[]; /* In text.s */ + +int main (void) +{ + clrscr (); + cprintf ("%s\r\nPress <RETURN>.\r\n", text); + cgetc (); + return EXIT_SUCCESS; +} +</code></tscreen> + +Compile the tutorial with + +<tscreen><verb> +cl65 -O -t osic1p -u __BOOT__ -o hello.lod hello.c text.s +</verb></tscreen> + +The program is configured for a Challenger 1P computer with, at least, 32 kB +of RAM. See the <url url="osi.html" +name="Ohio Scientifc-specific documentation"> for instructions about how to +compile for other RAM sizes. + +Plug a cassette player into your C1P computer; or, connect an RS-232 cable +between your C1P and a PC (set the PC's serial port to 300 Bits Per Second, +8 data bits, No parity, and 2 stop bits). (Turn on the computers.) + +Tap the "<bf/BREAK/" key, to display the boot prompt; then, tap the "<tt/M/" +key, to enter the 65V PROM monitor. Tap the "<tt/L/" key. Either start the +cassette player (with a tape of the program), or start a transfer of the +program file "<tt/hello.lod/" from the PC. After a while, you should see the +following text on the screen: + +<tscreen><verb> +Hello world! +Press <RETURN>. +</verb></tscreen> + +(Stop the cassette player.) After hitting the RETURN key, you should see the +boot prompt again. + +<sect2>WinOSI<p> +Available at <url +url="http://osi.marks-lab.com/#Emulator">: + +Emulates the Ohio Scientific Challenger computers in different configurations. +Configure it to emulate a C1P (model 600 board) with 32 kB of RAM. + +Compile the tutorial with the same command that is used to make the program +for a real machine. + +Start the emulator. Tap the "<tt/M/" key, to enter the 65V PROM monitor; then, +tap the "<tt/L/" key. If you had configured WinOSI to ask for a file when it +starts to read data from the serial port, then you will see a file dialog box; +otherwise, you must tap your host keyboard's F10 function key. Select the file +"<tt/hello.lod/". After a moment, you should see the following text on the +screen: + +<tscreen><verb> +Hello world! +Press <RETURN>. +</verb></tscreen> + +After hitting the RETURN key, you should see the boot prompt again. + +<sect2>C1Pjs<p> +Available at <url +url="http://www.pcjs.org/docs/c1pjs/">: + +Emulates the Ohio Scientific Challenger 1P computer in different configurations. +The 32 kB RAM machine that must be used with the default compiler settings is +<url url="http://www.pcjs.org/devices/c1p/machine/32kb/" name="here">. + +In addition to cc65, the <bf/srec_cat/ program from <url +url="http://srecord.sourceforge.net/" name="the SRecord tool collection"> +must be installed. Some Linux distributions also provide srecord directly as +an installable package. + +Compile the tutorial with this command line: + +<tscreen><verb> +cl65 -O -t osic1p hello.c text.s +</verb></tscreen> + +Convert the binary file into a text file that can be loaded via +the Ohio Scientific 65V PROM monitor, at start address 0x200: + +<tscreen><verb> +srec_cat hello -binary -offset 0x200 -o hello.c1p -Ohio_Scientific -execution-start-address=0x200 +</verb></tscreen> + +Open the URL that points to the 32 kB machine; and, wait until the emulator +has been loaded. Click on the "<bf/BREAK/" button to display the boot prompt; +then, press the "<tt/M/" key to enter the 65V PROM monitor. Click the +"<bf/Browse.../" button; and, select the file "<tt/hello.c1p/" that was +created as the output of the above invocation of the "<tt/srec_cat/" command. +Press the "<bf/Load/" button. You should see the following text on the screen: + +<tscreen><verb> +Hello world! +Press <RETURN>. +</verb></tscreen> + +After hitting the RETURN key, you should see the boot prompt again. + + <sect1>Contributions wanted<p> We need your help! Recommended emulators and instructions for other targets diff --git a/doc/nes.sgml b/doc/nes.sgml index ca9ce72b3..98c25b6af 100644 --- a/doc/nes.sgml +++ b/doc/nes.sgml @@ -69,7 +69,7 @@ Programs containing NES specific code may use the <tt/nes.h/ header file. <sect1>NES specific functions<p> <itemize> -<item>waitvblank +<item>waitvblank - wait until the start of vblank <item>get_tv </itemize> @@ -123,6 +123,14 @@ No extended memory drivers are currently available for the NES. </descrip><p> +The generic interface doesn't export the start and select buttons. To +test for those, use the defines in nes.h instead of the generic masks. + +Example: +<tscreen><verb> +if (joy_read(0) & KEY_A) +</verb></tscreen> + <sect1>Mouse drivers<p> diff --git a/doc/osi.sgml b/doc/osi.sgml new file mode 100644 index 000000000..ab1b4cee5 --- /dev/null +++ b/doc/osi.sgml @@ -0,0 +1,233 @@ +<!doctype linuxdoc system> + +<article> + +<title>Ohio Scientific-specific information for cc65 +<author> +<url url="mailto:stephan.muehlstrasser@web.de" name="Stephan Mühlstrasser">,<newline> +<url url="mailto:greg.king5@verizon.net" name="Greg King"> +<date>2015-03-17 + +<abstract> +An overview over the Ohio Scientific runtime system as it is implemented for the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the Ohio Scientific runtime system as it comes with the +cc65 C compiler. It describes the memory layout, Ohio Scientific-specific header files, +and any pitfalls specific to that platform. + +Please note that Ohio Scientific-specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + +<sect>Targets<p> + +Currently the target "osic1p" is implemented. This works for the Ohio Scientific +Challenger 1P machine and for the Briel Superboard /// replica. + +<sect>Program file formats<p> + +<descrip> + <tag/Binary, then text/ + The standard binary output format generated by the linker for the osic1p + target is a pure machine language program. + + For uploading into a real machine over its serial port or into an emulator, + that program must be converted into a text file that can be understood by + the 65V PROM monitor. For that purpose, the <bf/srec_cat/ program from <url + url="http://srecord.sourceforge.net/" name="the SRecord tool collection"> + can be used. + + Care must be taken that the <tt/-offset/ and <tt/-execution-start-address/ + options for the <bf/srec_cat/ program correspond to the start address + of the executable. + + Example for converting an executable "hello" file that was built for the + default start address $0200 to an uploadable file "hello.c1p": + + <tscreen><verb> + srec_cat hello -bin -of 0x200 -o hello.c1p -os -esa=0x200 + </verb></tscreen> + + <tag/Hybrid/ + The linker can create an alternate format that contains two parts: + <enum> + <item>A text header that is understood by the 65V PROM monitor. + It is a boot loader that reads the second part. + <item>The default binary code that is described above. + </enum> + + You can make the alternate format by adding the option <tt/-u __BOOT__/ to + <tt/cl65/'s or <tt/ld65/'s command lines. + + This format doesn't need to be converted. It is smaller than the text-only + format. But, it cannot be loaded by <url + url="http://www.pcjs.org/docs/c1pjs/" name="C1Pjs">; you must use the + SRecord-produced text-only format with that emulator. (However, if you know + that you never will use C1Pjs, then you can edit the + <tt>cfg/osic1p*.cfg</tt> files; uncomment the lines that import <tt/__BOOT__/. + Then, you won't need to use <tt/-u __BOOT__/ on your command lines.) + +</descrip> + +<sect>Memory layout<p> + +By default programs compiled for the osic1p target are configured for 32 kB RAM. +The RAM size can be configured via the symbol <tt/__HIMEM__/. + +Special locations: + +<descrip> + <tag/Program start address/ + The default start address is $0200. The start address is configurable + via the linker option <tt/--start-addr/. + + <tag/Stack/ + The C runtime stack is located at the top of RAM and growing downwards. + The size is configurable via the symbol <tt/__STACKSIZE__/. The default + stack size is $0400. + + <tag/Heap/ + The C heap is located at the end of the program and grows towards the C + runtime stack. + + <tag/Video RAM/ + The 1 kB video RAM is located at $D000. On the monitor, only a subset + of the available video RAM is visible. The address of the upper left corner + of the visible area is $D085 and corresponds to conio cursor + position (0, 0). + +</descrip><p> + +Example for building a program with start address $0300, stack size +$0200 and RAM size $2000: + +<tscreen><verb> +cl65 --start-addr 0x300 -Wl -D,__HIMEM__=$2000,-D,__STACKSIZE__=$0200 -t osic1p hello.c +</verb></tscreen> + +<sect>Linker configurations<p> + +The ld65 linker comes with a default config file "osic1p.cfg" for the Ohio Scientific +Challenger 1P, which is implicitly used via <tt/-t osic1p/. The +osic1p package comes with additional secondary linker config files, which are +used via <tt/-t osic1p -C <configfile>/. + +<sect1>Default config file (<tt/osic1p.cfg/)<p> + +The default configuration is tailored to C programs. + +<sect1><tt/osic1p-asm.cfg/<p> + +This configuration is made for assembler programmers who don't need a special +setup. + +To use this config file, assemble with <tt/-t osic1p/ and link with +<tt/-C osic1p-asm.cfg/. The former will make sure that correct runtime library +is used, while the latter supplies the actual config. When using <tt/cl65/, +use both command line options. + +Sample command lines for <tt/cl65/: + +<tscreen><verb> +cl65 -t osic1p -C osic1p-asm.cfg -o program source.s +cl65 -t osic1p -C osic1p-asm.cfg -u __BOOT__ -o program.lod source.s +</verb></tscreen> + +<sect>Platform-specific header files<p> + +Programs containing Ohio Scientific-specific code may use the <tt/osic1p.h/ +header file. + +<sect1>Ohio Scientific-specific functions<p> + +There are currently no special Ohio Scientific functions. + +<sect1>Hardware access<p> + +There is no specific support for direct hardware access. + +<sect>Loadable drivers<p> + +There are no loadable drivers available. + +<sect>Support for different screen layouts<p> + +By default the conio library uses a 24 columns by 24 lines screen layout +for the Challenger 1P, like under BASIC. In addition to that there is support +for other screen layouts with extra modules. + +There is a module <tt/screen-c1p-24x24.o/ in the OSI-specific +cc65 runtime library that contains all conio functions that depend +on the screen layout. No further configuration is needed for using the +default screen layout of the Challenger 1P. + +For other screen layouts additional versions of the screen module are +available. The linker finds these modules without further configuration +if they are specified on the compiler or linker command line. The +extra module then overrides the default module. + +Sample <tt/cl65/ command line to override the default screen +module with the module <tt/osic1p-screen-s3-32x28.o/: + +<tscreen><verb> +cl65 -o hello -t osic1p osic1p-screen-s3-32x28.o hello.c +</verb></tscreen> + +Currently the following extra screen configuration modules are implemented: + +<itemize> +<item><tt>osic1p-screen-s3-32x28.o</tt>: 32 columns by 28 lines mode +for Briel Superboard ///</item> +</itemize> + +<sect>Limitations<p> + +<sect1>stdio implementation<p> + +There is no support for stdio at the moment. + +<sect>Other hints<p> + +<sect1>Passing arguments to the program<p> + +There is currently no support for passing arguments to a program. + +<sect1>Program return code<p> + +The program return code currently has no effect. When the main() function +finishes, the boot prompt is shown again. + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + diff --git a/doc/pce.sgml b/doc/pce.sgml new file mode 100644 index 000000000..ba59c31a7 --- /dev/null +++ b/doc/pce.sgml @@ -0,0 +1,215 @@ +<!doctype linuxdoc system> + +<article> + +<title>PC-Engine (TurboGrafx) System specific information for cc65 +<author> +<url url="mailto:groepaz@gmx.net" name="Groepaz/Hitmen"> +<date>2015-07-14 + +<abstract> +An overview over the PCE runtime system as it is implemented for the +cc65 C compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + +This file contains an overview of the PCE runtime system as it comes +with the cc65 C compiler. It describes the memory layout, PCE specific header +files, available drivers, and any pitfalls specific to that platform. + +Please note that PCE specific functions are just mentioned here, they are +described in detail in the separate <url url="funcref.html" name="function +reference">. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information. + + +<sect>Binary format<p> + +The standard binary output format generated by the linker for the PCE target +is a cartridge image with no header. It is of course possible to change this +behaviour by using a modified startup file and linker config. + +<sect>Memory layout<p> + +cc65 generated programs with the default setup run with the I/O area and a +CHR bank enabled, which gives a usable memory range of $8000 - $FFF3. +All boot ROM entry points may be called directly without additional code. + +Special locations: + +<descrip> + <tag/Text screen and Font/ + The text screen is located at VRAM $0000, + the Font is located at VRAM $2000. + + <tag/Stack/ + The C runtime stack is located in system RAM at $3FFF and growing downwards. + + <tag/BSS and Data/ + + The BSS (uninitialized variables) and Data (initialized variables) sections are + placed one after the other into system RAM at $2000. + + <tag/Heap/ + The C heap is located after the end of the Data section and grows towards the C + runtime stack. + + <tag/Code/ + The startup code is located at $E000 in the System/Hardware bank. Further + code can be placed in other ROM banks, this must be done manually however. + +</descrip><p> + + + +<sect>Platform specific header files<p> + +Programs containing PCE specific code may use the <tt/pce.h/ header file. + + +<sect1>PCE specific functions<p> + +<itemize> +<item>waitvblank</item> +<item>get_tv (since all PCE systems are NTSC, this always returns TV_NTSC)</item> +</itemize> + + + +<sect1>Hardware access<p> + +The following pseudo variables declared in the <tt/pce.inc/ include file do +allow access to hardware located in the address space. + +<descrip> + + <tag><tt/PSG/</tag> + The <tt/PSG/ defines allow access to the PSG chip (Programmable Sound Generator). + + <tag><tt/VCE/</tag> + The <tt/VCE/ defines allow access to the VCE chip (Video Color Encoder). + + <tag><tt/VDC/</tag> + The <tt/VDC/ defines allow access to the VDC chip (Video Display Controller). + +</descrip><p> + + + +<sect>Loadable drivers<p> + +All drivers must be statically linked because no file I/O is available. +The names in the parentheses denote the symbols to be used for static linking of the drivers. + + +<sect1>Graphics drivers<p> + +No TGI graphics drivers are currently available for the PCE. + + +<sect1>Extended memory drivers<p> + +No extended memory drivers are currently available for the PCE. + + +<sect1>Joystick drivers<p> + +<descrip> + + <tag><tt/pce-stdjoy.joy (pce_stdjoy)/</tag> + A joystick driver for the standard two buttons joypad is available. + + Note that the japanese 6-button pad is currently not supported. + +</descrip><p> + + +<sect1>Mouse drivers<p> + +No mouse drivers are currently available for the PCE. + + +<sect1>RS232 device drivers<p> + +No serial drivers are currently available for the PCE. + + + +<sect>Limitations<p> + +<itemize> +<item>interruptor support in crt0 (and cfg) is missing +</itemize> + +<sect1>Disk I/O<p> + +The existing library for the PCE doesn't implement C file +I/O. There are no hacks for the <tt/read()/ and <tt/write()/ routines. + +To be more concrete, this limitation means that you cannot use any of the +following functions (and a few others): + +<itemize> +<item>printf +<item>fclose +<item>fopen +<item>fread +<item>fprintf +<item>fputc +<item>fscanf +<item>fwrite +<item>... +</itemize> + +<sect>Other hints<p> + +<itemize> +<item>a good emulator to use for PC-Engine is "mednafen" (<url url="http://mednafen.fobby.net/">) +</itemize> + +some useful resources on PCE coding: + +<itemize> +<item><url url="http://blog.blockos.org/?tag=pc-engine"> +<item><url url="http://pcedev.blockos.org/viewforum.php?f=5"> +<item><url url="http://www.romhacking.net/?page=documents&category=&platform=4&:game=&author=&perpage=20&level=&title=&desc=&docsearch=Go"> +<item><url url="http://archaicpixels.com/Main_Page"> + +<item><url url="http://www.magicengine.com/mkit/doc.html"> + +<item><url url="https://github.com/uli/huc"> +<item><url url="http://www.zeograd.com/parse.php?src=hucf"> +</itemize> + +<sect>License<p> + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> + + + diff --git a/doc/sim65.sgml b/doc/sim65.sgml new file mode 100644 index 000000000..24b43831c --- /dev/null +++ b/doc/sim65.sgml @@ -0,0 +1,125 @@ +<!doctype linuxdoc system> <!-- -*- text-mode -*- --> + +<article> + +<title>sim65 Users Guide +<author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> +<date>2016-01-05 + +<abstract> +sim65 is a simulator for 6502 and 65C02 CPUs. It allows to test target +independed code. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview<p> + + +sim65 is the only solution as part of the toolchain to execute code. The +binary needs to be compiled with <tt/--target sim6502/ or <tt/--target sim65c02/. + + +<sect>Usage<p> + +The simulator is called as follows: + +<tscreen><verb> + Usage: sim65 [options] file [arguments] + Short options: + -h Help (this text) + -v Increase verbosity + -V Print the simulator version number + -x <num> Exit simulator after <num> cycles + + Long options: + --help Help (this text) + --verbose Increase verbosity + --version Print the simulator version number +</verb></tscreen> + + +<sect1>Command line options in detail<p> + +Here is a description of all the command line options: + +<descrip> + + <tag><tt>-h, --help</tt></tag> + + Print the short option summary shown above. + + + <tag><tt>-v, --verbose</tt></tag> + + Increase the simulator verbosity. + + + <tag><tt>-V, --version</tt></tag> + + Print the version number of the utility. When submitting a bug report, + please include the operating system you're using, and the compiler + version. + + + <tag><tt>-x num</tt></tag> + + Exit simulator after num cycles. +</descrip> + + +<sect>Input and output<p> + +The simulator will read one binary file per invocation and can log the +program loading and paravirtualization calls to stderr. + +Example output for the command +<tscreen><verb> +sim65 --verbose --verbose samples/gunzip65 +</verb></tscreen> +<tscreen><verb> +Loaded `samples/gunzip65' at $0200-$151F +PVWrite ($0001, $13C9, $000F) +GZIP file name:PVWrite ($0001, $151F, $0001) + +PVRead ($0000, $FFD7, $0001) +PVOpen ("", $0001) +PVRead ($0003, $1520, $6590) +PVClose ($0003) +PVWrite ($0001, $13D9, $000F) +Not GZIP formatPVWrite ($0001, $151F, $0001) + +PVExit ($01) +</verb></tscreen> + + + +<sect>Copyright<p> + +sim65 (and all cc65 binutils) are (C) Copyright 1998-2000 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following conditions +do apply: + +This software is provided 'as-is', without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/smc.sgml b/doc/smc.sgml index 240c78e7b..4f3e2ace4 100644 --- a/doc/smc.sgml +++ b/doc/smc.sgml @@ -224,7 +224,7 @@ These marcos are determined to get, set and change arguments of instructions: <label id="Change branch"> <tag><tt>SMC_ChangeBranch label, destination (, register)</tt></tag> - Used to modify the destination of a branch instruction. If the adress offset + Used to modify the destination of a branch instruction. If the address offset exceeds the supported range of 8-bit of the 6502, a error will be thrown. Example: @@ -296,7 +296,7 @@ SMC GetK, { LDX #SMC_Value } <tag><tt>SMC_TransferLowByte label, value (, register)</tt></tag> Does the same as '<tt>SMC_TransferValue</tt>' but should be used for - low-bytes of adresses for better readability. + low-bytes of addresses for better readability. Example: <tscreen><verb> @@ -312,7 +312,7 @@ SMC LoadData, { LDA $2000 } <tag><tt>SMC_LoadLowByte label (, register)</tt></tag> Does the same as '<tt>SMC_LoadValue</tt>' but should be used for low-bytes - of adresses for better readability. + of addresses for better readability. Example: <tscreen><verb> @@ -329,7 +329,7 @@ SMC LoadData, { LDA $2000 } <tag><tt>SMC_StoreLowByte label (, register)</tt></tag> Does the same as '<tt>SMC_StoreValue</tt>' but should be used for low-bytes - of adresses for better readability. + of addresses for better readability. Example: <tscreen><verb> @@ -352,7 +352,7 @@ SMC StoreCollisionData, { STY $2200 } <tag><tt>SMC_TransferHighByte label, value (, register)</tt></tag> Loads and stores the given value via the named register to the high-byte - adress portion of an SMC-instruction. + address portion of an SMC-instruction. Example: <tscreen><verb> @@ -370,7 +370,7 @@ PlayOtherSound: <label id="Load high-byte"> <tag><tt>SMC_LoadHighByte label (, register)</tt></tag> - Loads the high-byte part of an SMC-instruction adress to the given register. + Loads the high-byte part of an SMC-instruction address to the given register. Example: <tscreen><verb> @@ -387,7 +387,7 @@ SMC GetVolume { LDA $3200,x } <label id="Store high-byte"> <tag><tt>SMC_StoreHighByte label (, register)</tt></tag> - Stores the high-byte adress part of an SMC-instruction from the given + Stores the high-byte address part of an SMC-instruction from the given register. Example: @@ -407,7 +407,7 @@ SMC GetSoundData, { LDA Level1Base+Sound, y } </verb></tscreen> - <label id="Transfer single adress"> + <label id="Transfer single address"> <tag><tt>SMC_TransferAddressSingle label, address (, register)</tt></tag> Transfers the contents of the given address via the given register to the @@ -428,7 +428,7 @@ SMC GetChar, { LDA SMC_AbsAdr, x } </verb></tscreen> - <label id="Transfer adress"> + <label id="Transfer address"> <tag><tt>SMC_TransferAddress label, address</tt></tag> Loads contents of given address to A/X and stores the result to SMC @@ -559,11 +559,11 @@ allowing reuse of some instructions. 8: SMC FirstIncHighByte, { SMC_OperateOnHighByte inc, StoreAccuFirstSection } ; code will be overwritten to 'beq RestoreCode' (*) 9: ... 10: SMC_TransferOpcode FirstIncHighByte, OPC_BEQ , x ; change code marked above with (*) -11: SMC_TransferValue FirstIncHighByte, #(restoreCode - RestoreCodeBranchBaseAdr-2), x ; set relative adress to 'RestoreCode' +11: SMC_TransferValue FirstIncHighByte, #(restoreCode - RestoreCodeBranchBaseAdr-2), x ; set relative address to 'RestoreCode' 12: ... 13: restoreCode: 14: SMC_TransferOpcode FirstIncHighByte, OPC_INC_abs , x ; restore original code... -15: SMC_TransferValue FirstIncHighByte, #(<(StoreToFirstSection+2)), x ; (second byte of inc contained low-byte of adress) +15: SMC_TransferValue FirstIncHighByte, #(<(StoreToFirstSection+2)), x ; (second byte of inc contained low-byte of address) 16: ... </verb></tscreen> diff --git a/include/ace.h b/include/ace.h index 8d9130085..fba672227 100644 --- a/include/ace.h +++ b/include/ace.h @@ -2,14 +2,14 @@ /* */ /* ace.h */ /* */ -/* ACE system specific definitions */ +/* ACE system-specific definitions */ /* */ /* */ /* */ -/* (C) 1998-2001 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2015, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -61,9 +61,9 @@ struct aceDirentBuf { char ad_name [17]; /* Name itself, ASCIIZ */ }; -int aceDirOpen (char* dir); -int aceDirClose (int handle); -int aceDirRead (int handle, struct aceDirentBuf* buf); +int __cdecl__ aceDirOpen (char* dir); +int __cdecl__ aceDirClose (int handle); +int __cdecl__ aceDirRead (int handle, struct aceDirentBuf* buf); /* Type of an ACE key. Key in low byte, shift mask in high byte */ typedef unsigned int aceKey; @@ -92,23 +92,23 @@ typedef unsigned int aceKey; #define aceOP_RPTRATE 11 /* Key repeat rate */ /* Console functions */ -void aceConWrite (char* buf, size_t count); -void aceConPutLit (int c); -void aceConPos (unsigned x, unsigned y); -void aceConGetPos (unsigned* x, unsigned* y); +void __cdecl__ aceConWrite (char* buf, size_t count); +void __cdecl__ aceConPutLit (int c); +void __cdecl__ aceConPos (unsigned x, unsigned y); +void __cdecl__ aceConGetPos (unsigned* x, unsigned* y); unsigned aceConGetX (void); unsigned aceConGetY (void); -char* aceConInput (char* buf, unsigned initial); +char __cdecl__* aceConInput (char* buf, unsigned initial); int aceConStopKey (void); aceKey aceConGetKey (void); -int aceConKeyAvail (aceKey* key); -void aceConKeyMat (char* matrix); -void aceConSetOpt (unsigned char opt, unsigned char val); -int aceConGetOpt (unsigned char opt); +int __cdecl__ aceConKeyAvail (aceKey* key); +void __cdecl__ aceConKeyMat (char* matrix); +void __cdecl__ aceConSetOpt (unsigned char opt, unsigned char val); +int __cdecl__ aceConGetOpt (unsigned char opt); /* Misc stuff */ -int aceMiscIoPeek (unsigned addr); -void aceMiscIoPoke (unsigned addr, unsigned char val); +int __cdecl__ aceMiscIoPeek (unsigned addr); +void __cdecl__ aceMiscIoPoke (unsigned addr, unsigned char val); diff --git a/include/assert.h b/include/assert.h index 87bc4ff02..504964dc2 100644 --- a/include/assert.h +++ b/include/assert.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2015, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -42,7 +42,7 @@ #ifdef NDEBUG # define assert(expr) #else -extern void _afailed (const char*, unsigned); +extern void __fastcall__ _afailed (const char*, unsigned); # define assert(expr) ((expr)? (void)0 : _afailed(__FILE__, __LINE__)) #endif diff --git a/include/cbm.h b/include/cbm.h index 730b0b49e..701924d57 100644 --- a/include/cbm.h +++ b/include/cbm.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2012, Ullrich von Bassewitz */ +/* (C) 1998-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -222,7 +222,7 @@ void cbm_k_unlsn (void); -unsigned int cbm_load (const char* name, unsigned char device, void* data); +unsigned int __fastcall__ cbm_load (const char* name, unsigned char device, void* data); /* Loads file "name", from given device, to given address -- or, to the load ** address of the file if "data" is the null pointer (like load"name",8,1 ** in BASIC). diff --git a/include/conio.h b/include/conio.h index 54667a3ca..8638e94d4 100644 --- a/include/conio.h +++ b/include/conio.h @@ -77,6 +77,10 @@ # include <lynx.h> #elif defined(__NES__) # include <nes.h> +#elif defined(__OSIC1P__) +# include <osic1p.h> +#elif defined(__PCE__) +# include <pce.h> #endif diff --git a/include/dbg.h b/include/dbg.h index 734ca06b8..7b4f67e31 100644 --- a/include/dbg.h +++ b/include/dbg.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 1998-2000, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -88,7 +88,7 @@ unsigned __fastcall__ DbgDisAsmLen (unsigned Addr); int __fastcall__ DbgIsRAM (unsigned Addr); /* Return true if we can read and write the given address */ -char* DbgMemDump (unsigned Addr, char* Buf, unsigned char Len); +char* __cdecl__ DbgMemDump (unsigned Addr, char* Buf, unsigned char Len); /* Create a line of a memory dump in the given buffer. The buffer contains ** the starting address (4 digits hex), then Len bytes in this format: ** "AAAA__XX_YY_ZZ_...". The passed char buffer must hold Len*3+5 bytes diff --git a/include/lynx.h b/include/lynx.h index e9c702994..72f3d5bfd 100644 --- a/include/lynx.h +++ b/include/lynx.h @@ -2,7 +2,7 @@ /* */ /* lynx.h */ /* */ -/* Lynx system specific definitions */ +/* Lynx system-specific definitions */ /* */ /* */ /* */ @@ -109,25 +109,25 @@ extern void lynx_160_102_16_tgi[]; /* Referred to by tgi_static_stddrv[] */ /* Sound support */ /*****************************************************************************/ -void lynx_snd_init (); +void lynx_snd_init (void); /* Initialize the sound driver */ -void lynx_snd_pause (); +void lynx_snd_pause (void); /* Pause sound */ -void lynx_snd_continue (); +void lynx_snd_continue (void); /* Continue sound after pause */ void __fastcall__ lynx_snd_play (unsigned char channel, unsigned char *music); /* Play tune on channel */ -void lynx_snd_stop (); +void lynx_snd_stop (void); /* Stop sound on all channels */ void __fastcall__ lynx_snd_stop_channel (unsigned char channel); /* Stop sound on all channels */ -unsigned char lynx_snd_active(); +unsigned char lynx_snd_active(void); /* Show which channels are active */ /*****************************************************************************/ diff --git a/include/mouse.h b/include/mouse.h index ac75956c0..8bd9a00ff 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -122,6 +122,16 @@ struct mouse_callbacks { /* The default mouse callbacks */ extern const struct mouse_callbacks mouse_def_callbacks; +#if defined(__CBM__) + +/* The default mouse pointer shape used by the default mouse callbacks */ +extern const unsigned char mouse_def_pointershape[63]; + +/* The default mouse pointer color used by the default mouse callbacks */ +extern const unsigned char mouse_def_pointercolor; + +#endif + /* The name of the standard mouse driver for a platform */ extern const char mouse_stddrv[]; @@ -208,6 +218,3 @@ unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data); /* End of mouse.h */ #endif - - - diff --git a/include/nes.h b/include/nes.h index 3ad442280..a472a0f3c 100644 --- a/include/nes.h +++ b/include/nes.h @@ -90,7 +90,72 @@ /* No support for dynamically loadable drivers */ #define DYN_DRV 0 +/* The joystick keys - all keys are supported */ +#define KEY_A 0x01 +#define KEY_B 0x02 +#define KEY_SELECT 0x04 +#define KEY_START 0x08 +#define KEY_UP 0x10 +#define KEY_DOWN 0x20 +#define KEY_LEFT 0x40 +#define KEY_RIGHT 0x80 +/* Define hardware */ + +/* Picture Processing Unit */ +struct __ppu { + unsigned char control; + unsigned char mask; /* color; show sprites, background */ + signed char volatile const status; + struct { + unsigned char address; + unsigned char data; + } sprite; + unsigned char scroll; + struct { + unsigned char address; + unsigned char data; + } vram; +}; +#define PPU (*(struct __ppu*)0x2000) +#define SPRITE_DMA (APU.sprite.dma) + +/* Audio Processing Unit */ +struct __apu { + struct { + unsigned char control; /* duty, counter halt, volume/envelope */ + unsigned char ramp; + unsigned char period_low; /* timing */ + unsigned char len_period_high; /* length, timing */ + } pulse[2]; + struct { + unsigned char counter; /* counter halt, linear counter */ + unsigned char unused; + unsigned char period_low; /* timing */ + unsigned char len_period_high; /* length, timing */ + } triangle; + struct { + unsigned char control; /* counter halt, volume/envelope */ + unsigned char unused; + unsigned char period; /* loop, timing */ + unsigned char len; /* length */ + } noise; + struct { + unsigned char control; /* IRQ, loop, rate */ + unsigned char output; /* output value */ + unsigned char address; + unsigned char length; + } delta_mod; /* delta pulse-code modulation */ + struct { + unsigned char dma; + } sprite; + signed char volatile status; + unsigned char unused; + unsigned char fcontrol; +}; +#define APU (*(struct __apu*)0x4000) + +#define JOYPAD ((unsigned char volatile[2])0x4016) /* The addresses of the static drivers */ extern void nes_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ diff --git a/include/osic1p.h b/include/osic1p.h new file mode 100644 index 000000000..57fe0cd24 --- /dev/null +++ b/include/osic1p.h @@ -0,0 +1,47 @@ +/*****************************************************************************/ +/* */ +/* 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 diff --git a/include/pce.h b/include/pce.h new file mode 100644 index 000000000..7700654c8 --- /dev/null +++ b/include/pce.h @@ -0,0 +1,94 @@ +/*****************************************************************************/ +/* */ +/* pce.h */ +/* */ +/* PC-Engine system specific definitions */ +/* */ +/* */ +/* */ +/* (C) 2015 Groepaz/Hitmen */ +/* */ +/* */ +/* 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 _PCE_H +#define _PCE_H + +/* Check for errors */ +#if !defined(__PCE__) +# error This module may only be used when compiling for the PCE! +#endif + +#define CH_HLINE 1 +#define CH_VLINE 2 +#define CH_CROSS 3 +#define CH_ULCORNER 4 +#define CH_URCORNER 5 +#define CH_LLCORNER 6 +#define CH_LRCORNER 7 +#define CH_TTEE 8 +#define CH_BTEE 9 +#define CH_LTEE 10 +#define CH_RTEE 11 + +#define CH_ENTER 13 +#define CH_PI 18 + +/* Color defines (CBM compatible, for conio) */ +#define COLOR_BLACK 0x00 +#define COLOR_WHITE 0x01 +#define COLOR_RED 0x02 +#define COLOR_CYAN 0x03 +#define COLOR_VIOLET 0x04 +#define COLOR_GREEN 0x05 +#define COLOR_BLUE 0x06 +#define COLOR_YELLOW 0x07 +#define COLOR_ORANGE 0x08 +#define COLOR_BROWN 0x09 +#define COLOR_LIGHTRED 0x0A +#define COLOR_GRAY1 0x0B +#define COLOR_GRAY2 0x0C +#define COLOR_LIGHTGREEN 0x0D +#define COLOR_LIGHTBLUE 0x0E +#define COLOR_GRAY3 0x0F + +#define TV_NTSC 0 +#define TV_PAL 1 +#define TV_OTHER 2 + +/* No support for dynamically loadable drivers */ +#define DYN_DRV 0 + +/* The addresses of the static drivers */ +extern void pce_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ + +#define JOY_FIRE_B 5 +#define JOY_SELECT 6 +#define JOY_RUN 7 + +void waitvblank (void); +/* Wait for the vertical blanking */ + +/* NOTE: all PCE are NTSC */ +#define get_tv() TV_NTSC +/* Return the video mode the machine is using. */ + +/* End of pce.h */ +#endif diff --git a/include/stdlib.h b/include/stdlib.h index eac5629a8..3103172d8 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -107,12 +107,12 @@ int __fastcall__ atoi (const char* s); long __fastcall__ atol (const char* s); int __fastcall__ atexit (void (*exitfunc) (void)); void* __fastcall__ bsearch (const void* key, const void* base, size_t n, - size_t size, int (*cmp) (const void*, const void*)); + size_t size, int __fastcall__ (* cmp) (const void*, const void*)); div_t __fastcall__ div (int numer, int denom); void __fastcall__ exit (int ret) __attribute__ ((noreturn)); char* __fastcall__ getenv (const char* name); void __fastcall__ qsort (void* base, size_t count, size_t size, - int (*compare) (const void*, const void*)); + int __fastcall__ (* compare) (const void*, const void*)); long __fastcall__ strtol (const char* nptr, char** endptr, int base); unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base); int __fastcall__ system (const char* s); diff --git a/include/time.h b/include/time.h index c70ffa718..12f130f52 100644 --- a/include/time.h +++ b/include/time.h @@ -99,6 +99,9 @@ unsigned _clocks_per_sec (void); #elif defined(__NES__) # define CLK_TCK 50 /* POSIX */ # define CLOCKS_PER_SEC 50 /* ANSI */ +#elif defined(__PCE__) +# define CLK_TCK 60 /* POSIX */ +# define CLOCKS_PER_SEC 60 /* ANSI */ #elif defined(__GEOS__) # define CLK_TCK 1 /* POSIX */ # define CLOCKS_PER_SEC 1 /* ANSI */ diff --git a/include/zlib.h b/include/zlib.h index 9bc5dcb27..8fa6a2bd1 100644 --- a/include/zlib.h +++ b/include/zlib.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000-2001 Piotr Fusik <fox@scene.pl> */ +/* (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. */ @@ -83,8 +83,8 @@ unsigned __fastcall__ inflatemem (char* dest, const char* source); */ -int uncompress (char* dest, unsigned* destLen, - const char* source, unsigned sourceLen); +int __fastcall__ uncompress (char* dest, unsigned* destLen, + const char* source, unsigned sourceLen); /* Original zlib description: diff --git a/libsrc/Makefile b/libsrc/Makefile index 6a801695a..d70ad5a31 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -24,6 +24,8 @@ TARGETS = apple2 \ $(GEOS) \ lynx \ nes \ + osic1p \ + pce \ sim6502 \ sim65c02 \ supervision diff --git a/libsrc/apple2/crt0.s b/libsrc/apple2/crt0.s index 4a7463b27..f061b212b 100644 --- a/libsrc/apple2/crt0.s +++ b/libsrc/apple2/crt0.s @@ -11,7 +11,7 @@ .import callmain .import __LC_START__, __LC_LAST__ ; Linker generated .import __INIT_RUN__, __INIT_SIZE__ ; Linker generated - .import __ZPSAVE_RUN__ ; Linker generated + .import __INITBSS_RUN__ ; Linker generated .include "zeropage.inc" .include "apple2.inc" @@ -29,14 +29,14 @@ bit $C081 ; Set the source start address. - lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__) - ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__) + lda #<(__INITBSS_RUN__ + __INIT_SIZE__) + ldy #>(__INITBSS_RUN__ + __INIT_SIZE__) sta $9B sty $9C ; Set the source last address. - lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__) - ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__) + lda #<(__INITBSS_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__) + ldy #>(__INITBSS_RUN__ + __INIT_SIZE__ + __LC_LAST__ - __LC_START__) sta $96 sty $97 @@ -46,19 +46,19 @@ sta $94 sty $95 - ; Call into the Applesoft Block Transfer Utility -- which handles zero- + ; Call into Applesoft Block Transfer Up -- which handles zero- ; sized blocks well -- to move the content of the LC memory area. - jsr $D396 ; BLTU + 3 + jsr $D39A ; BLTU2 ; Set the source start address. - lda #<__ZPSAVE_RUN__ - ldy #>__ZPSAVE_RUN__ + lda #<__INITBSS_RUN__ + ldy #>__INITBSS_RUN__ sta $9B sty $9C ; Set the source last address. - lda #<(__ZPSAVE_RUN__ + __INIT_SIZE__) - ldy #>(__ZPSAVE_RUN__ + __INIT_SIZE__) + lda #<(__INITBSS_RUN__ + __INIT_SIZE__) + ldy #>(__INITBSS_RUN__ + __INIT_SIZE__) sta $96 sty $97 @@ -68,9 +68,9 @@ sta $94 sty $95 - ; Call into the Applesoft Block Transfer Utility -- which handles moving + ; Call into Applesoft Block Transfer Up -- which handles moving ; overlapping blocks upwards well -- to move the INIT segment. - jsr $D396 ; BLTU + 3 + jsr $D39A ; BLTU2 ; Delegate all further processing, to keep the STARTUP segment small. jsr init @@ -164,10 +164,6 @@ basic: lda HIMEM : sta sp stx sp+1 - ; Enable interrupts, as old ProDOS versions (i.e. 1.1.1) - ; jump to SYS and BIN programs with interrupts disabled. - cli - ; Call the module constructors. jsr initlib @@ -205,7 +201,7 @@ q_param:.byte $04 ; param_count ; Final jump when we're done done: jmp DOSWARM ; Potentially patched at runtime - .segment "ZPSAVE" + .segment "INITBSS" zpsave: .res zpspace diff --git a/libsrc/apple2/exec.s b/libsrc/apple2/exec.s index c486306bb..d24de604c 100644 --- a/libsrc/apple2/exec.s +++ b/libsrc/apple2/exec.s @@ -23,11 +23,29 @@ oserr: jsr popname ; Preserves A jmp __mappederrno _exec: + ; Save cmdline + sta ptr4 + stx ptr4+1 + ; Get and push name jsr popax jsr pushname bne oserr + ; ProDOS TechRefMan, chapter 5.1.5.1: + ; "The complete or partial pathname of the system program + ; is stored at $280, starting with a length byte." + ; In fact BASIC.SYSTEM does the same for BLOAD and BRUN of + ; binary programs so we should do the same too in any case + ; especially as _we_ rely on it in mainargs.s for argv[0] + ldy #$00 + lda (sp),y + tay +: lda (sp),y + sta $0280,y + dey + bpl :- + ; Set pushed name lda sp ldx sp+1 @@ -52,24 +70,14 @@ _exec: lda mliparam + MLI::INFO::FILE_TYPE cmp #$FF ; SYS file? bne binary ; No, check for BIN file + sta file_type ; Save file type for cmdline handling - ; ProDOS TechRefMan, chapter 5.1.5.1: - ; "The complete or partial pathname of the system program - ; is stored at $280, starting with a length byte." - ldy #$00 - lda (sp),y - tay -: lda (sp),y - sta $0280,y - dey - bpl :- - ; SYS programs replace BASIC.SYSTEM so set in the ProDOS system bit map ; protection for pages $80 - $BF just in case BASIC.SYSTEM is there now ldx #$0F ; Start with protection for pages $B8 - $BF lda #%00000001 ; Protect only system global page : sta $BF60,x ; Set protection for 8 pages - lda #$00 ; Protect no page + lda #%00000000 ; Protect no page dex bpl :- bmi prodos ; Branch always @@ -112,7 +120,7 @@ setbuf: lda #$00 ; Low byte dex dex dex - + ; Set I/O buffer sta mliparam + MLI::OPEN::IO_BUFFER stx mliparam + MLI::OPEN::IO_BUFFER+1 @@ -126,7 +134,7 @@ setbuf: lda #$00 ; Low byte stx level beq :+ dec LEVEL - + ; Open file : lda #OPEN_CALL ldx #OPEN_COUNT @@ -158,8 +166,27 @@ setbuf: lda #$00 ; Low byte bit $C080 .endif + ; Reset stack as we already passed + ; the point of no return anyway + ldx #$FF + txs + + ; Store up to 127 chars of cmdline (if any) + ; including terminating zero in stack page + ldy #$00 + lda ptr4+1 ; NULL? + beq :++ ; Yes, store as '\0' +: lda (ptr4),y +: sta $0100,y + beq :+ ; '\0' stored, done + iny + cpy #$7E + bcc :-- + lda #$00 ; '\0' + beq :- ; Branch always + ; Call loader stub after C libary shutdown - lda #<target +: lda #<target ldx #>target sta done+1 stx done+2 @@ -177,16 +204,58 @@ level : .res 1 source: jsr $BF00 .byte READ_CALL .word read_param - bcs :+ + bcs error ; Close program file jsr $BF00 .byte CLOSE_CALL .word close_param - bcs :+ + bcs error + + ; Check for cmdline handling + lda $0100 ; Valid cmdline? + beq jump ; No, jump to program right away + ldx file_type ; SYS file? + bne system ; Yes, check for startup filename + + ; Store REM and cmdline in BASIC input buffer + lda #$B2 ; REM token + bne :++ ; Branch always +: inx + lda a:$0100-1,x +: sta $0200,x + bne :-- + beq jump ; Branch always + + ; Check for startup filename support + ; ProDOS TechRefMan, chapter 5.1.5.1: + ; "$2000 is a jump instruction. $2003 and $2004 are $EE." +system: lda $2000 + cmp #$4C + bne jump + lda $2003 + cmp #$EE + bne jump + lda $2004 + cmp #$EE + bne jump + + ; Store cmdline in startup filename buffer + ldx #$01 +: lda a:$0100-1,x + beq :+ + sta $2006,x + inx + cpx $2005 ; Buffer full? + bcc :- ; No, continue +: dex + stx $2006 ; Store cmdline length ; Go for it ... - jmp (data_buffer) +jump: jmp (data_buffer) + +file_type = * - source + target + .byte $00 read_param = * - source + target .byte $04 ; PARAM_COUNT @@ -204,7 +273,7 @@ close_ref = * - source + target ; Quit to ProDOS dispatcher quit = * - source + target -: jsr $BF00 +error: jsr $BF00 .byte $65 ; QUIT .word quit_param diff --git a/libsrc/apple2/initcwd.s b/libsrc/apple2/initcwd.s index 044076e3f..7af29c75e 100644 --- a/libsrc/apple2/initcwd.s +++ b/libsrc/apple2/initcwd.s @@ -21,20 +21,21 @@ initcwd: jsr callmli ; Check for null prefix - lda __cwd + ldx __cwd beq done ; Remove length byte and trailing slash - sta tmp1 - ldx #$01 -: lda __cwd,x - sta __cwd - 1,x + dex + stx tmp1 + ldx #$00 +: lda __cwd + 1,x + sta __cwd,x inx cpx tmp1 bcc :- ; Add terminating zero lda #$00 - sta __cwd - 1,x + sta __cwd,x done: rts diff --git a/libsrc/apple2/irq.s b/libsrc/apple2/irq.s index c81fa7108..0b0555695 100644 --- a/libsrc/apple2/irq.s +++ b/libsrc/apple2/irq.s @@ -21,6 +21,10 @@ initirq: .byte $40 ; Alloc interrupt .addr i_param bcs prterr + + ; Enable interrupts, as old ProDOS versions (i.e. 1.1.1) + ; jump to SYS and BIN programs with interrupts disabled. + cli rts ; Print error message and exit diff --git a/libsrc/apple2/mainargs.s b/libsrc/apple2/mainargs.s index 6b0df4ded..2e809dc56 100644 --- a/libsrc/apple2/mainargs.s +++ b/libsrc/apple2/mainargs.s @@ -34,12 +34,12 @@ MAXARGS = 10 ; ProDOS stores the filename in the second half of BASIC's input buffer, so -; there are 128 characters left. At least 7 characters are necessary for the -; CALLxxxx:REM so 121 characters may be used before overwriting the ProDOS -; filename. As we don't want to put further restrictions on the command-line -; length we reserve those 121 characters terminated by a zero. +; there are 128 characters left. At least 1 character is necessary for the +; REM so 127 characters (including the terminating zero) may be used before +; overwriting the ProDOS filename. As we don't want to further restrict the +; command-line length we reserve those 127 characters. -BUF_LEN = 122 +BUF_LEN = 127 BASIC_BUF = $200 FNAM_LEN = $280 @@ -176,4 +176,4 @@ argv: .addr FNAM .bss -buffer: .res BUF_LEN \ No newline at end of file +buffer: .res BUF_LEN diff --git a/libsrc/apple2/targetutil/loader.s b/libsrc/apple2/targetutil/loader.s index 0173f6105..a6cc13cef 100644 --- a/libsrc/apple2/targetutil/loader.s +++ b/libsrc/apple2/targetutil/loader.s @@ -22,14 +22,14 @@ READ_CALL = $CA CLOSE_CALL = $CC FILE_NOT_FOUND_ERR = $46 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ------------------------------------------------------------------------ .import __CODE_0300_SIZE__, __DATA_0300_SIZE__ .import __CODE_0300_LOAD__, __CODE_0300_RUN__ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ------------------------------------------------------------------------ -.segment "DATA_2000" + .segment "DATA_2000" GET_FILE_INFO_PARAM: .byte $0A ;PARAM_COUNT @@ -57,9 +57,9 @@ LOADING: ELLIPSES: .byte " ...", $0D, $0D, $00 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ------------------------------------------------------------------------ -.segment "DATA_0300" + .segment "DATA_0300" READ_PARAM: .byte $04 ;PARAM_COUNT @@ -81,22 +81,22 @@ QUIT_PARAM: FILE_NOT_FOUND: .asciiz "... File Not Found" - + ERROR_NUMBER: .asciiz "... Error $" PRESS_ANY_KEY: .asciiz " - Press Any Key " -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ------------------------------------------------------------------------ -.segment "CODE_2000" + .segment "CODE_2000" jmp :+ .byte $EE .byte $EE - .byte 65 -STARTUP:.res 65 + .byte $7F +STARTUP:.res $7F ; Reset stack : ldx #$FF @@ -104,8 +104,8 @@ STARTUP:.res 65 ; Relocate CODE_0300 and DATA_0300 ldx #<(__CODE_0300_SIZE__ + __DATA_0300_SIZE__) -: lda __CODE_0300_LOAD__ - 1,x - sta __CODE_0300_RUN__ - 1,x +: lda __CODE_0300_LOAD__-1,x + sta __CODE_0300_RUN__-1,x dex bne :- @@ -118,23 +118,23 @@ STARTUP:.res 65 ; Add trailing '\0' to pathname tax lda #$00 - sta PATHNAME + 1,x + sta PATHNAME+1,x ; Copy ProDOS startup filename and trailing '\0' to stack ldx STARTUP lda #$00 - beq :++ ; bra -: lda STARTUP + 1,x + beq :++ ; Branch always +: lda STARTUP+1,x : sta STACK,x dex - bpl :-- + bpl :-- ; Provide some user feedback lda #<LOADING ldx #>LOADING jsr PRINT - lda #<(PATHNAME + 1) - ldx #>(PATHNAME + 1) + lda #<(PATHNAME+1) + ldx #>(PATHNAME+1) jsr PRINT lda #<ELLIPSES ldx #>ELLIPSES @@ -159,16 +159,16 @@ STARTUP:.res 65 ; Get load address from aux-type lda FILE_INFO_ADDR - ldx FILE_INFO_ADDR + 1 + ldx FILE_INFO_ADDR+1 sta READ_ADDR - stx READ_ADDR + 1 + stx READ_ADDR+1 ; It's high time to leave this place jmp __CODE_0300_RUN__ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ------------------------------------------------------------------------ -.segment "CODE_0300" + .segment "CODE_0300" jsr MLI .byte READ_CALL @@ -180,15 +180,15 @@ STARTUP:.res 65 .word CLOSE_PARAM bcs ERROR - ; Copy REM token and startup filename to BASIC input buffer + ; Copy REM and startup filename to BASIC input buffer ldx #$00 - lda #$B2 - bne :++ ; bra + lda #$B2 ; REM token + bne :++ ; Branch always : inx - lda a:STACK - 1,x + lda a:STACK-1,x : sta BUF,x bne :-- - + ; Go for it ... jmp (READ_ADDR) @@ -207,7 +207,7 @@ PRINT: : ora #$80 jsr COUT iny - bne :-- ; bra + bne :-- ; Branch always : rts ERROR: @@ -216,7 +216,7 @@ ERROR: lda #<FILE_NOT_FOUND ldx #>FILE_NOT_FOUND jsr PRINT - beq :++ ; bra + beq :++ ; Branch always : pha lda #<ERROR_NUMBER ldx #>ERROR_NUMBER @@ -230,5 +230,3 @@ ERROR: jsr MLI .byte QUIT_CALL .word QUIT_PARAM - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/libsrc/atari/dosdetect.s b/libsrc/atari/dosdetect.s index c60ac479b..654da55b5 100644 --- a/libsrc/atari/dosdetect.s +++ b/libsrc/atari/dosdetect.s @@ -5,7 +5,7 @@ ; .include "atari.inc" - .constructor detect,26 + .constructor detect, 26 .export __dos_type ; ------------------------------------------------------------------------ diff --git a/libsrc/atari/getargs.s b/libsrc/atari/getargs.s index fdae55364..fb3b7bc03 100644 --- a/libsrc/atari/getargs.s +++ b/libsrc/atari/getargs.s @@ -15,7 +15,7 @@ SPACE = 32 ; SPACE char. .import __argc, __argv .importzp ptr1 .import __dos_type - .constructor initmainargs,25 + .constructor initmainargs, 25 ; -------------------------------------------------------------------------- ; Get command line diff --git a/libsrc/atari/getdefdev.s b/libsrc/atari/getdefdev.s index 13aa12e04..47d8714e6 100644 --- a/libsrc/atari/getdefdev.s +++ b/libsrc/atari/getdefdev.s @@ -19,7 +19,7 @@ .export __getdefdev ; get default device .export __defdev ; this is the default device string (e.g. "D1:") .ifdef DYNAMIC_DD - .constructor __getdefdev,24 + .constructor __getdefdev, 24 .endif ; Get default device (LBUF will be destroyed!!) diff --git a/libsrc/atari/initcwd.s b/libsrc/atari/initcwd.s index d7b574314..c292e72c3 100644 --- a/libsrc/atari/initcwd.s +++ b/libsrc/atari/initcwd.s @@ -9,6 +9,8 @@ .proc initcwd + lda #0 + sta __cwd jsr findfreeiocb bne oserr lda #GETCWD @@ -19,13 +21,13 @@ sta ICBLH,x jsr CIOV bmi oserr - ldx #0 ; ATEOL -> \0 -: lda __cwd,x - inx + ldx #$FF ; ATEOL -> \0 +: inx + lda __cwd,x cmp #ATEOL bne :- lda #0 - sta __cwd-1,x + sta __cwd,x oserr: rts .endproc diff --git a/libsrc/atari/mcbpm.s b/libsrc/atari/mcbpm.s index b546faced..c5c5dd433 100644 --- a/libsrc/atari/mcbpm.s +++ b/libsrc/atari/mcbpm.s @@ -10,8 +10,8 @@ .include "atari.inc" .importzp sp .export _mouse_pm_callbacks - .constructor pm_init,27 - .destructor pm_down,7 + .constructor pm_init, 27 + .destructor pm_down ; get mouse shape data .import mouse_pm_bits diff --git a/libsrc/atari5200/conioscreen.s b/libsrc/atari5200/conioscreen.s index 412dd582d..660276675 100644 --- a/libsrc/atari5200/conioscreen.s +++ b/libsrc/atari5200/conioscreen.s @@ -7,9 +7,10 @@ SCREEN_BUF_SIZE = 20 * 24 SCREEN_BUF = $4000 - SCREEN_BUF_SIZE - .code .export screen_setup_20x24 + .segment "INIT" + screen_setup_20x24: ; initialize SAVMSC @@ -79,5 +80,4 @@ dlist: .repeat 3 .assert ((* >> 10) = (dlist >> 10)), error, "Display list crosses 1K boundary" - .end diff --git a/libsrc/atmos/bashdr.s b/libsrc/atmos/bashdr.s new file mode 100644 index 000000000..e09bc9fec --- /dev/null +++ b/libsrc/atmos/bashdr.s @@ -0,0 +1,24 @@ +; +; 2010-11-14, Ullrich von Bassewitz +; 2014-09-06, Greg King +; +; This module supplies a small BASIC stub program that uses CALL +; to jump to the machine-language code that follows it. +; + + ; The following symbol is used by the linker config. file + ; to force this module to be included into the output file. + .export __BASHDR__:abs = 1 + + +.segment "BASHDR" + + .addr Next + .word .version ; Line number + .byte $BF,'#' ; CALL token, mark number as hexadecimal + .byte <(Start >> 8 ) + '0' + (Start >> 8 > $09) * $07 + .byte <(Start >> 4 & $0F) + '0' + (Start >> 4 & $0F > $09) * $07 + .byte <(Start & $0F) + '0' + (Start & $0F > $09) * $07 + .byte $00 ; End of BASIC line +Next: .addr $0000 ; BASIC program end marker +Start: diff --git a/libsrc/atmos/crt0.s b/libsrc/atmos/crt0.s index 1d919f348..e789b28c2 100644 --- a/libsrc/atmos/crt0.s +++ b/libsrc/atmos/crt0.s @@ -2,39 +2,18 @@ ; Startup code for cc65 (Oric version) ; ; By Debrune Jérôme <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org> -; 2014-08-22, Greg King +; 2015-01-09, Greg King ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import callmain, zerobss - .import __RAM_START__, __RAM_SIZE__ - .import __ZPSAVE_LOAD__, __STACKSIZE__ + .import __RAM_START__, __RAM_SIZE__, __STACKSIZE__ .include "zeropage.inc" .include "atmos.inc" -; ------------------------------------------------------------------------ -; Oric tape header - -.segment "TAPEHDR" - - .byte $16, $16, $16 ; Sync bytes - .byte $24 ; End of header marker - - .byte $00 ; $2B0 - .byte $00 ; $2AF - .byte $80 ; $2AE Machine code flag - .byte $C7 ; $2AD Autoload flag - .dbyt __ZPSAVE_LOAD__ - 1 ; $2AB - .dbyt __RAM_START__ ; $2A9 - .byte $00 ; $2A8 - .byte ((.VERSION >> 8) & $0F) + '0' - .byte ((.VERSION >> 4) & $0F) + '0' - .byte (.VERSION & $0F) + '0' - .byte $00 ; Zero terminated compiler version - ; ------------------------------------------------------------------------ ; Place the startup code in a special segment. @@ -52,7 +31,8 @@ L1: lda sp,x jsr zerobss -; Unprotect screen columns 0 and 1. +; Currently, color isn't supported on the text screen. +; Unprotect screen columns 0 and 1 (where each line's color codes would sit). lda STATUS sta stsave @@ -79,7 +59,7 @@ L1: lda sp,x ; Call the module destructors. This is also the exit() entry. -_exit: jsr donelib ; Run module destructors +_exit: jsr donelib ; Restore the system stuff. @@ -102,9 +82,23 @@ L2: lda zpsave,x ; ------------------------------------------------------------------------ -.segment "ZPSAVE" +.segment "ZPSAVE1" -zpsave: .res zpspace +zpsave: + +; This padding is needed by a bug in the ROM. +; (The CLOAD command starts BASIC's variables table on top of the last byte +; that was loaded [instead of at the next address].) +; This is overlaid on a buffer, so that it doesn't use extra space in RAM. + + .byte 0 + +; The segments "ZPSAVE1" and "ZPSAVE2" always must be together. +; They create a single object (the zpsave buffer). + +.segment "ZPSAVE2" + + .res zpspace - 1 ; ------------------------------------------------------------------------ diff --git a/libsrc/atmos/tapehdr.s b/libsrc/atmos/tapehdr.s new file mode 100644 index 000000000..d90c908eb --- /dev/null +++ b/libsrc/atmos/tapehdr.s @@ -0,0 +1,31 @@ +; +; Based on code by Debrune Jérôme <jede@oric.org> +; 2015-01-08, Greg King +; + + ; The following symbol is used by the linker config. file + ; to force this module to be included into the output file. + .export __TAPEHDR__:abs = 1 + + ; These symbols, also, come from the configuration file. + .import __BASHDR_LOAD__, __ZPSAVE1_LOAD__, __AUTORUN__, __PROGFLAG__ + + +; ------------------------------------------------------------------------ +; Oric cassette-tape header + +.segment "TAPEHDR" + + .byte $16, $16, $16 ; Sync bytes + .byte $24 ; Beginning-of-header marker + + .byte $00 ; $2B0 + .byte $00 ; $2AF + .byte <__PROGFLAG__ ; $2AE Language flag ($00=BASIC, $80=machine code) + .byte <__AUTORUN__ ; $2AD Auto-run flag ($C7=run, $00=only load) + .dbyt __ZPSAVE1_LOAD__ ;$2AB Address of end of file + .dbyt __BASHDR_LOAD__ ; $2A9 Address of start of file + .byte $00 ; $2A8 + + ; File name (a maximum of 17 characters), zero-terminated + .asciiz .sprintf("%u", .time) diff --git a/libsrc/c128/crt0.s b/libsrc/c128/crt0.s index 9bfdca49f..4c6a0f7d9 100644 --- a/libsrc/c128/crt0.s +++ b/libsrc/c128/crt0.s @@ -108,7 +108,7 @@ L2: lda zpsave,x ; ------------------------------------------------------------------------ ; Data -.segment "ZPSAVE" +.segment "INITBSS" zpsave: .res zpspace diff --git a/libsrc/c128/emd/c128-ram.s b/libsrc/c128/emd/c128-ram.s index bef0a15ee..3fc52c9cc 100644 --- a/libsrc/c128/emd/c128-ram.s +++ b/libsrc/c128/emd/c128-ram.s @@ -51,7 +51,7 @@ PAGES = (TOPMEM - BASE) / 256 ; Data. .bss -curpage: .res 1 ; Current page number +curpage: .res 2 ; Current page number window: .res 256 ; Memory "window" @@ -70,7 +70,7 @@ INSTALL: stx curpage+1 ; Invalidate the current page inx txa ; A = X = EM_ERR_OK - rts +; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. @@ -107,6 +107,7 @@ MAP: sta curpage lda #<ptr1 sta FETVEC + sei ; Transfer one page @@ -115,6 +116,7 @@ MAP: sta curpage sta window,y iny bne @L1 + cli ; Return the memory window @@ -146,6 +148,7 @@ COMMIT: lda curpage ; Get the current page lda #<ptr1 sta STAVEC + sei ; Transfer one page. Y must be zero on entry @@ -154,6 +157,7 @@ COMMIT: lda curpage ; Get the current page jsr STASH iny bne @L1 + cli ; Done @@ -196,6 +200,7 @@ COPYFROM: ; Copy full pages ldy #$00 + sei @L1: ldx #MMU_CFG_RAM1 jsr FETCH sta (ptr2),y @@ -223,7 +228,8 @@ COPYFROM: ; Done -@L4: rts +@L4: cli + rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure @@ -261,6 +267,7 @@ COPYTO: sta ptr3 ; Copy full pages ldy #$00 + sei @L1: lda (ptr2),y ldx #MMU_CFG_RAM1 jsr STASH @@ -288,5 +295,5 @@ COPYTO: sta ptr3 ; Done -@L4: rts - +@L4: cli + rts diff --git a/libsrc/c128/mainargs.s b/libsrc/c128/mainargs.s index fb5fd1554..dcd5a11bd 100644 --- a/libsrc/c128/mainargs.s +++ b/libsrc/c128/mainargs.s @@ -30,8 +30,7 @@ MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name - +NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special INIT segment, ; which may be reused after the startup code is run @@ -42,26 +41,26 @@ initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. -; Because the buffer, that we're copying into, was zeroed out, -; we don't need to add a NUL character. -; + + lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 - ldy #NAME_LEN - 1 ; limit the length + ldy #NAME_LEN ; Limit the length + bne L1 ; Branch always L0: lda #FNAM ; Load vector address for FETCH routine ldx FNAM_BANK ; Load bank for FETCH routine jsr INDFET ; Load byte from (FETVEC),y - sta name,y ; Save byte from filename -L1: dey +L1: sta name,y ; Save byte from filename + dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. -; + ldx #0 L2: lda BASIC_BUF,x - beq done ; no "rem," no args. + beq done ; No "rem," no args. inx cmp #REM bne L2 @@ -73,7 +72,7 @@ next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces - beq next ; + beq next ; Found start of next argument. We've incremented the pointer in X already, so ; it points to the second character of the argument. This is useful since we @@ -128,15 +127,13 @@ done: lda #<argv stx __argv + 1 rts -; These arrays are zeroed before initmainargs is called. -; char name[16+1]; -; char* argv[MAXARGS+1]={name}; -; -.bss +.segment "INITBSS" + term: .res 1 name: .res NAME_LEN + 1 .data + +; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 - diff --git a/libsrc/c128/mcbdefault.s b/libsrc/c128/mcbdefault.s index 01c54efca..1951129a6 100644 --- a/libsrc/c128/mcbdefault.s +++ b/libsrc/c128/mcbdefault.s @@ -7,7 +7,10 @@ ; be called from an interrupt handler ; + .constructor initmcb .export _mouse_def_callbacks + .import _mouse_def_pointershape + .import _mouse_def_pointercolor .include "mouse-kernel.inc" .include "c128.inc" @@ -15,16 +18,45 @@ .macpack generic ; Sprite definitions. The first value can be changed to adjust the number -; of the sprite used for the mouse. +; of the sprite used for the mouse. All others depend on this value. MOUSE_SPR = 0 ; Sprite used for the mouse +MOUSE_SPR_MEM = $0E00 ; Memory location MOUSE_SPR_MASK = $01 .shl MOUSE_SPR ; Positive mask MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask VIC_SPR_X = (VIC_SPR0_X + 2*MOUSE_SPR) ; Sprite X register VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register +; -------------------------------------------------------------------------- +; Initialize the mouse sprite. + +.segment "INIT" + +initmcb: + +; Copy the mouse sprite data + + ldx #64 - 1 +@L0: lda _mouse_def_pointershape,x + sta MOUSE_SPR_MEM,x + dex + bpl @L0 + +; Set the mouse sprite pointer + + lda #<(MOUSE_SPR_MEM / 64) + sta $07F8 + MOUSE_SPR + +; Set the mouse sprite color + + lda _mouse_def_pointercolor + sta VIC_SPR0_COLOR + MOUSE_SPR + rts + ; -------------------------------------------------------------------------- ; Hide the mouse pointer. Always called with interrupts disabled. +.code + hide: lda #MOUSE_SPR_NMASK and VIC_SPR_ENA diff --git a/libsrc/c128/randomize.s b/libsrc/c128/randomize.s index 5c57e04be..ae63184a4 100644 --- a/libsrc/c128/randomize.s +++ b/libsrc/c128/randomize.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 05.11.2002 +; 2002-11-05, Ullrich von Bassewitz +; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ @@ -12,6 +13,6 @@ __randomize: ldx VIC_HLINE ; Use VIC rasterline as high byte - lda TIME ; Use 60HZ clock as low byte + lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/c128/systime.s b/libsrc/c128/systime.s index 0a7f8f367..e12d016b8 100644 --- a/libsrc/c128/systime.s +++ b/libsrc/c128/systime.s @@ -63,6 +63,7 @@ BCD2dec:tax ; Constructor that writes to the 1/10 sec register of the TOD to kick it ; into action. If this is not done, the clock hangs. We will read the register ; and write it again, ignoring a possible change in between. +.segment "INIT" .proc initsystime @@ -78,7 +79,6 @@ BCD2dec:tax .endproc - ;---------------------------------------------------------------------------- ; TM struct with date set to 1970-01-01 .data @@ -92,4 +92,3 @@ TM: .word 0 ; tm_sec .word 0 ; tm_wday .word 0 ; tm_yday .word 0 ; tm_isdst - diff --git a/libsrc/c16/crt0.s b/libsrc/c16/crt0.s index 0180ad671..c4d179529 100644 --- a/libsrc/c16/crt0.s +++ b/libsrc/c16/crt0.s @@ -90,7 +90,7 @@ L2: lda zpsave,x ; ------------------------------------------------------------------------ -.segment "ZPSAVE" +.segment "INITBSS" zpsave: .res zpspace diff --git a/libsrc/c16/mainargs.s b/libsrc/c16/mainargs.s index 0a402d27d..db93ae2e6 100644 --- a/libsrc/c16/mainargs.s +++ b/libsrc/c16/mainargs.s @@ -28,10 +28,9 @@ .include "plus4.inc" - MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name +NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special INIT segment, ; which may be reused after the startup code is run @@ -42,25 +41,25 @@ initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. -; Because the buffer, that we're copying into, was zeroed out, -; we don't need to add a NUL character. -; + + lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 - ldy #NAME_LEN - 1 ; limit the length + ldy #NAME_LEN ; Limit the length + bne L1 ; Branch always L0: lda #FNAM ; Vector address jsr FETCH ; Load byte from RAM - sta name,y -L1: dey +L1: sta name,y + dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. -; + ldx #0 L2: lda BASIC_BUF,x - beq done ; no "rem," no args. + beq done ; No "rem," no args. inx cmp #REM bne L2 @@ -72,7 +71,7 @@ next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces - beq next ; + beq next ; Found start of next argument. We've incremented the pointer in X already, so ; it points to the second character of the argument. This is useful since we @@ -127,15 +126,13 @@ done: lda #<argv stx __argv + 1 rts -; These arrays are zeroed before initmainargs is called. -; char name[16+1]; -; char* argv[MAXARGS+1]={name}; -; -.bss +.segment "INITBSS" + term: .res 1 name: .res NAME_LEN + 1 .data + +; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 - diff --git a/libsrc/c16/randomize.s b/libsrc/c16/randomize.s index 903a0809a..796ad118b 100644 --- a/libsrc/c16/randomize.s +++ b/libsrc/c16/randomize.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 05.11.2002 +; 2002-11-05, Ullrich von Bassewitz +; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ @@ -12,6 +13,6 @@ __randomize: ldx TED_VLINELO ; Use TED rasterline as high byte - lda TIME ; Use 60HZ clock as low byte + lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/c64/bordercolor.s b/libsrc/c64/bordercolor.s new file mode 100644 index 000000000..73dfc0a99 --- /dev/null +++ b/libsrc/c64/bordercolor.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; unsigned char __fastcall__ bordercolor (unsigned char color); +; + + + .export _bordercolor + + .include "c64.inc" + +_bordercolor: + ldx VIC_BORDERCOLOR ; get old value + sta VIC_BORDERCOLOR ; set new value + txa + rts + diff --git a/libsrc/c64/color.s b/libsrc/c64/color.s index bfc371931..86d6aefe8 100644 --- a/libsrc/c64/color.s +++ b/libsrc/c64/color.s @@ -3,11 +3,10 @@ ; ; unsigned char __fastcall__ textcolor (unsigned char color); ; unsigned char __fastcall__ bgcolor (unsigned char color); -; unsigned char __fastcall__ bordercolor (unsigned char color); ; - .export _textcolor, _bgcolor, _bordercolor + .export _textcolor, _bgcolor .include "c64.inc" @@ -23,11 +22,3 @@ _bgcolor: sta VIC_BG_COLOR0 ; set new value txa rts - - -_bordercolor: - ldx VIC_BORDERCOLOR ; get old value - sta VIC_BORDERCOLOR ; set new value - txa - rts - diff --git a/libsrc/c64/crt0.s b/libsrc/c64/crt0.s index 24fe4376b..78268422b 100644 --- a/libsrc/c64/crt0.s +++ b/libsrc/c64/crt0.s @@ -4,12 +4,12 @@ .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup + .import initlib, donelib - .import zerobss - .import callmain - .import RESTOR, BSOUT, CLRCH - .import __RAM_START__, __RAM_SIZE__ ; Linker generated - .import __STACKSIZE__ ; Linker generated + .import moveinit, zerobss, callmain + .import BSOUT + .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated + .import __STACKSIZE__ ; from configure file .importzp ST .include "zeropage.inc" @@ -23,14 +23,6 @@ Start: -; Save the zero-page locations that we need. - - ldx #zpspace-1 -L1: lda sp,x - sta zpsave,x - dex - bpl L1 - ; Switch to the second charset. lda #14 @@ -39,31 +31,34 @@ L1: lda sp,x ; Switch off the BASIC ROM. lda $01 - pha ; Remember the value + sta mmusave ; Save the memory configuration and #$F8 ora #$06 ; Enable Kernal+I/O, disable BASIC sta $01 -; Clear the BSS data. - - jsr zerobss - -; Save some system settings; and, set up the stack. - - pla - sta mmusave ; Save the memory configuration - tsx stx spsave ; Save the system stack ptr - lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) - sta sp - lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) - sta sp+1 ; Set argument stack ptr +; Allow some re-entrancy by skipping the next task if it already was done. +; This sometimes can let us rerun the program without reloading it. -; Call the module constructors. + ldx move_init + beq L0 - jsr initlib +; Move the INIT segment from where it was loaded (over the bss segments) +; into where it must be run (over the BSS segment). + + jsr moveinit + dec move_init ; Set to false + +; Save space by putting some of the start-up code in the INIT segment, +; which can be re-used by the BSS segment, the heap and the C stack. + +L0: jsr runinit + +; Clear the BSS data. + + jsr zerobss ; Push the command-line arguments; and, call main(). @@ -98,14 +93,47 @@ L2: lda zpsave,x rts + +; ------------------------------------------------------------------------ + +.segment "INIT" + +runinit: + +; Save the zero-page locations that we need. + + ldx #zpspace-1 +L1: lda sp,x + sta zpsave,x + dex + bpl L1 + +; Set up the stack. + + lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) + ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) + sta sp + stx sp+1 ; Set argument stack ptr + +; Call the module constructors. + + jmp initlib + + ; ------------------------------------------------------------------------ ; Data -.segment "ZPSAVE" +.data + +; These two variables were moved out of the BSS segment, and into DATA, because +; we need to use them before INIT is moved off of BSS, and before BSS is zeroed. + +mmusave:.res 1 +spsave: .res 1 + +move_init: + .byte 1 + +.segment "INITBSS" zpsave: .res zpspace - -.bss - -spsave: .res 1 -mmusave:.res 1 diff --git a/libsrc/c64/extra/soft80.s b/libsrc/c64/extra/soft80.s new file mode 100644 index 000000000..d445c85c0 --- /dev/null +++ b/libsrc/c64/extra/soft80.s @@ -0,0 +1,52 @@ +; +; Groepaz/Hitmen, 12.10.2015 +; +; import/overload stubs for the soft80 implementation + + .include "../soft80.inc" + + ; soft80_cgetc.s + .import soft80_cgetc + .export _cgetc := soft80_cgetc ; cgetc.s + + ; soft80_color.s + .import soft80_textcolor + .import soft80_bgcolor + .export _textcolor := soft80_textcolor ; color.s + .export _bgcolor := soft80_bgcolor ; color.s + + ; soft80_cputc.s + .import soft80_cputc + .import soft80_cputcxy + .import soft80_cputdirect + .import soft80_putchar + .import soft80_newline + .import soft80_plot + .export _cputc := soft80_cputc ; cputc.s + .export _cputcxy := soft80_cputcxy ; cputc.s + .export cputdirect := soft80_cputdirect ; cputc.s + .export putchar := soft80_putchar ; cputc.s + .export newline := soft80_newline ; cputc.s + .export plot := soft80_plot ; cputc.s + + ; soft80_kclrscr.s + .import soft80_kclrscr + .export _clrscr := soft80_kclrscr ; clrscr.s + + ; soft80_kplot.s + .import soft80_kplot + .export PLOT := soft80_kplot ; kplot.s + + ; soft80_kscreen.s + .import soft80_screensize + .export screensize := soft80_screensize ; _scrsize.s + ; FIXME: use _scrsize.s/remove soft80_scrsize.s + ;.export SCREEN := soft80_screensize ; kernal func (kernal.s) + + ; VIC sprite data for the mouse pointer + .export mcb_spritememory := soft80_spriteblock + .export mcb_spritepointer := (soft80_vram + $03F8) + + ; Chars used by chline () and cvline () + .exportzp chlinechar = CH_HLINE + .exportzp cvlinechar = CH_VLINE diff --git a/libsrc/c64/extra/soft80mono.s b/libsrc/c64/extra/soft80mono.s new file mode 100644 index 000000000..6fd2c687c --- /dev/null +++ b/libsrc/c64/extra/soft80mono.s @@ -0,0 +1,55 @@ +; +; Groepaz/Hitmen, 19.10.2015 +; +; import/overload stubs for the monochrome soft80 implementation +; +; - optimized for size, almost 1k smaller footprint than the full color version +; - textcolor() sets one common text color for the whole screen +; + .include "../soft80.inc" + + ; soft80mono_cgetc.s + .import soft80mono_cgetc + .export _cgetc := soft80mono_cgetc ; cgetc.s + + ; soft80mono_color.s + .import soft80mono_textcolor + .import soft80mono_bgcolor + .export _textcolor := soft80mono_textcolor ; color.s + .export _bgcolor := soft80mono_bgcolor ; color.s + + ; soft80mono_cputc.s + .import soft80mono_cputc + .import soft80mono_cputcxy + .import soft80mono_cputdirect + .import soft80mono_putchar + .import soft80mono_newline + .import soft80mono_plot + .export _cputc := soft80mono_cputc ; cputc.s + .export _cputcxy := soft80mono_cputcxy ; cputc.s + .export cputdirect := soft80mono_cputdirect ; cputc.s + .export putchar := soft80mono_putchar ; cputc.s + .export newline := soft80mono_newline ; cputc.s + .export plot := soft80mono_plot ; cputc.s + + ; soft80mono_kclrscr.s + .import soft80mono_kclrscr + .export _clrscr := soft80mono_kclrscr ; clrscr.s + + ; soft80mono_kplot.s + .import soft80mono_kplot + .export PLOT := soft80mono_kplot ; kplot.s + + ; soft80_kscreen.s + .import soft80_screensize + .export screensize := soft80_screensize ; _scrsize.s + ; FIXME: use _scrsize.s/remove soft80_scrsize.s + ;.export SCREEN := soft80_screensize ; kernal func (kernal.s) + + ; VIC sprite data for the mouse pointer + .export mcb_spritememory := soft80_spriteblock + .export mcb_spritepointer := (soft80_vram + $03F8) + + ; Chars used by chline () and cvline () + .exportzp chlinechar = CH_HLINE + .exportzp cvlinechar = CH_VLINE diff --git a/libsrc/c64/mainargs.s b/libsrc/c64/mainargs.s index 1c9031eb0..a31c1b54f 100644 --- a/libsrc/c64/mainargs.s +++ b/libsrc/c64/mainargs.s @@ -28,10 +28,9 @@ .include "c64.inc" - MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name +NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special INIT segment, ; which may be reused after the startup code is run @@ -42,24 +41,24 @@ initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. -; Because the buffer, that we're copying into, was zeroed out, -; we don't need to add a NUL character. -; + + lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 - ldy #NAME_LEN - 1 ; limit the length + ldy #NAME_LEN ; Limit the length + bne L1 ; Branch always L0: lda (FNAM),y - sta name,y -L1: dey +L1: sta name,y + dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. -; + ldx #0 L2: lda BASIC_BUF,x - beq done ; no "rem," no args. + beq done ; No "rem," no args. inx cmp #REM bne L2 @@ -71,7 +70,7 @@ next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces - beq next ; + beq next ; Found start of next argument. We've incremented the pointer in X already, so ; it points to the second character of the argument. This is useful since we @@ -126,15 +125,13 @@ done: lda #<argv stx __argv + 1 rts -; These arrays are zeroed before initmainargs is called. -; char name[16+1]; -; char* argv[MAXARGS+1]={name}; -; -.bss +.segment "INITBSS" + term: .res 1 name: .res NAME_LEN + 1 .data + +; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 - diff --git a/libsrc/c64/mcbdefault.s b/libsrc/c64/mcbdefault.s index ffeed45b3..cd36d8515 100644 --- a/libsrc/c64/mcbdefault.s +++ b/libsrc/c64/mcbdefault.s @@ -7,7 +7,12 @@ ; be called from an interrupt handler ; + .constructor initmcb .export _mouse_def_callbacks + .import _mouse_def_pointershape + .import _mouse_def_pointercolor + .import mcb_spritememory + .import mcb_spritepointer .include "mouse-kernel.inc" .include "c64.inc" @@ -22,9 +27,49 @@ MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask VIC_SPR_X = (VIC_SPR0_X + 2*MOUSE_SPR) ; Sprite X register VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register +; -------------------------------------------------------------------------- +; Initialize the mouse sprite. + +.segment "INIT" + +initmcb: + +; Make all RAM accessible + + lda #$30 + ldy $01 + sei + sta $01 + +; Copy the mouse sprite data + + ldx #64 - 1 +@L0: lda _mouse_def_pointershape,x + sta mcb_spritememory,x + dex + bpl @L0 + +; Set the mouse sprite pointer + + lda #<(mcb_spritememory / 64) + sta mcb_spritepointer + MOUSE_SPR + +; Restore memory configuration + + sty $01 + cli + +; Set the mouse sprite color + + lda _mouse_def_pointercolor + sta VIC_SPR0_COLOR + MOUSE_SPR + rts + ; -------------------------------------------------------------------------- ; Hide the mouse pointer. Always called with interrupts disabled. +.code + hide: lda #MOUSE_SPR_NMASK and VIC_SPR_ENA diff --git a/libsrc/c64/mcbspritedata.s b/libsrc/c64/mcbspritedata.s new file mode 100644 index 000000000..2c7aa1491 --- /dev/null +++ b/libsrc/c64/mcbspritedata.s @@ -0,0 +1,4 @@ +; VIC sprite data for the mouse pointer + + .export mcb_spritememory := $0340 + .export mcb_spritepointer := $07F8 diff --git a/libsrc/c64/randomize.s b/libsrc/c64/randomize.s index c77d6b411..d74bae91e 100644 --- a/libsrc/c64/randomize.s +++ b/libsrc/c64/randomize.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 05.11.2002 +; 2002-11-05, Ullrich von Bassewitz +; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ @@ -12,6 +13,6 @@ __randomize: ldx VIC_HLINE ; Use VIC rasterline as high byte - lda TIME ; Use 60HZ clock as low byte + lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/c64/soft80.inc b/libsrc/c64/soft80.inc new file mode 100644 index 000000000..ca5c713ce --- /dev/null +++ b/libsrc/c64/soft80.inc @@ -0,0 +1,46 @@ +; +; Groepaz/Hitmen, 12.10.2015 +; +; internal constants for the soft80 implementation + +soft80_lo_charset = $d000 +soft80_hi_charset = $d400 +soft80_vram = $d800 ; ram under i/o +soft80_colram = $d800 ; color ram (used for temp. storage) +soft80_spriteblock = $dc00 ; 64 bytes reserved for pointer sprite data + +; tables for kplot +soft80_bitmapxlo = $dc40 ; (80 bytes) +soft80_bitmapxhi = $dc40 + 80 ; (80 bytes) +soft80_vramlo = $dc40 + 160 ; (25 bytes) +; align to next page for speed +soft80_vramhi = $dd00 ; (25 bytes) +soft80_bitmapylo = $dd00 + 25 ; (25 bytes) +soft80_bitmapyhi = $dd00 + 50 ; (25 bytes) + +soft80_bitmap = $e000 + +charsperline = 80 +screenrows = 25 + +; FIXME: these should match petscii and perhaps come from a common cbm.inc? +CH_ESC = 95 +CH_HLINE = 96 +CH_CROSS = 123 +CH_VLINE = 125 +CH_PI = 126 +CH_LTEE = 171 +CH_URCORNER = 174 +CH_LLCORNER = 173 +CH_ULCORNER = 176 +CH_BTEE = 177 +CH_TTEE = 178 +CH_RTEE = 179 +CH_LRCORNER = 189 + +;------------------------------------------------------------------------------- +; set to 0 to disable the color-ram "voodoo" for debugging purposes +.define SOFT80COLORVOODOO 1 +; set to 0 to disable special case optimization for the "space" character +.define SOFT80FASTSPACE 1 + diff --git a/libsrc/c64/soft80_cgetc.s b/libsrc/c64/soft80_cgetc.s new file mode 100644 index 000000000..ae0e23857 --- /dev/null +++ b/libsrc/c64/soft80_cgetc.s @@ -0,0 +1,90 @@ +; +; Groepaz/Hitmen, 11.10.2015 +; +; high level implementation for the soft80 implementation +; +; char cgetc (void); +; + + .export soft80_cgetc + .import soft80_internal_cellcolor, soft80_internal_cursorxlsb + .import cursor + .importzp tmp1 + + .include "c64.inc" + .include "soft80.inc" + +soft80_cgetc: + lda KEY_COUNT ; Get number of characters + bne @L3 ; Jump if there are already chars waiting + + sec + jsr invertcursor ; set cursor on or off accordingly + +@L1: lda KEY_COUNT ; wait for key + beq @L1 + + clc + jsr invertcursor ; set cursor on or off accordingly + +@L3: jsr KBDREAD ; Read char and return in A + ldx #0 + rts + +; Switch the cursor on or off (invert) + +invertcursor: + lda cursor + bne @invert + rts +@invert: + + sei + lda $01 ; enable RAM under I/O + pha + lda #$34 + sta $01 + + ldy #$00 + jsr setcolor + + ldx soft80_internal_cursorxlsb +@lp1: + lda (SCREEN_PTR),y + eor nibble,x + sta (SCREEN_PTR),y + iny + cpy #8 + bne @lp1 + + pla + sta $01 ; enable I/O + cli + rts + + ; do not use soft80_putcolor here to make sure the cursor is always + ; shown using the current textcolor without disturbing the "color voodoo" + ; in soft80_cputc +setcolor: + ;ldy #0 ; is 0 + bcs @set + ; restore old value + lda tmp1 + sta (CRAM_PTR),y ; vram + rts +@set: + ; save old value + lda (CRAM_PTR),y ; vram + sta tmp1 + lda soft80_internal_cellcolor + sta (CRAM_PTR),y ; vram + rts + + .rodata +nibble: .byte $f0, $0f + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import soft80_init +conio_init = soft80_init diff --git a/libsrc/c64/soft80_charset.s b/libsrc/c64/soft80_charset.s new file mode 100644 index 000000000..69fd3527f --- /dev/null +++ b/libsrc/c64/soft80_charset.s @@ -0,0 +1,182 @@ +; +; Groepaz/Hitmen, 12.10.2015 +; +; character set for use with the soft80 implementations +; + +; the format of the data follows the following layout: +; +; - to avoid unnecessary petscii->screencode conversions, the order of the +; individual characters is different to the C64 ROM charset: +; - $00 - $1f screencodes $60 - $7f (petscii codes $a0 - $bf) +; - $20 - $3f screencodes $20 - $3f (petscii codes $20 - $3f) +; - $40 - $5f screencodes $00 - $1f (petscii codes $40 - $5f) +; - $60 - $7f screencodes $40 - $5f (petscii codes $60 - $7f) +; - only 128 characters are defined here, the soft80 implementation will invert +; the graphics data for inverted display on the fly. +; - since the charset is 4 by 8 pixels, only the lower 4bit of each byte is +; used. the upper bits have to be 0. +; - finally the lower 4bits are "inverted", ie a space character is represented +; as $0f, $0f, $0f, $0f, $0f, $0f, $0f, $0f +; +; the graphics data is arranged differently to normal C64 charsets for speed, +; first comes the first row of all characters, then the second row in the next +; block, etc. like this: +; +; +000 ....xxxx ......xx ....xxxx ........ +; +080 ....xxxx ......xx ....xxxx ....xxxx +; +100 ....xxxx ......xx ....xxxx ....xxxx +; +180 ....x..x ......xx ....xxxx ....xxxx +; +200 ....x..x ......xx ........ ....xxxx +; +280 ....xxxx ......xx ........ ....xxxx +; +300 ....xxxx ......xx ........ ....xxxx +; +380 ....xxxx ......xx ........ ....xxxx +; [...] +; +040 ....x.xx ....xxxx ....xxxx ....xxxx +; +0c0 .....x.x ....xxxx .....xxx ....xxxx +; +140 .......x ....x.xx .....xxx ....x..x +; +1c0 .......x ....xx.x ......xx .....xxx +; +240 .....xxx ....x..x .....x.x .....xxx +; +2c0 .....x.x .....x.x .....x.x .....xxx +; +340 ....x.xx ....x..x ......xx ....x..x +; +3c0 ....xxxx ....xxxx ....xxxx ....xxxx + + .export soft80_charset + + .segment "INIT" +soft80_charset: + .byte $0f,$03,$0f,$00,$0f,$07,$05,$0e + .byte $0f,$05,$0e,$0b,$0f,$0b,$0f,$0f + .byte $0f,$0b,$0f,$0b,$07,$07,$0e,$00 + .byte $00,$0f,$0e,$0f,$0c,$0b,$03,$03 + .byte $0f,$0b,$05,$05,$0b,$05,$0b,$0b + .byte $0d,$07,$0f,$0f,$0f,$0f,$0f,$0d + .byte $0b,$0b,$0b,$0b,$05,$01,$0b,$01 + .byte $0b,$0b,$0f,$0f,$0d,$0f,$07,$0b + .byte $0b,$0f,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$09,$07,$03,$0b,$0f + .byte $0f,$0b,$03,$0b,$03,$01,$01,$0b + .byte $05,$01,$09,$05,$07,$05,$05,$0b + .byte $03,$0b,$03,$0b,$01,$05,$05,$05 + .byte $05,$05,$01,$0b,$07,$0b,$0f,$0a + + .byte $0f,$03,$0f,$0f,$0f,$07,$05,$0e + .byte $0f,$0a,$0e,$0b,$0f,$0b,$0f,$0f + .byte $0f,$0b,$0f,$0b,$07,$07,$0e,$00 + .byte $00,$0f,$0e,$0f,$0c,$0b,$03,$03 + .byte $0f,$0b,$05,$05,$09,$05,$05,$0b + .byte $0b,$0b,$05,$0b,$0f,$0f,$0f,$0d + .byte $05,$0b,$05,$05,$05,$07,$05,$05 + .byte $05,$05,$0f,$0f,$0b,$0f,$0b,$05 + .byte $05,$0f,$07,$0f,$0d,$0f,$09,$0f + .byte $07,$0b,$0d,$07,$03,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$0b,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0b,$07,$0b,$0b,$0b + .byte $0f,$0b,$05,$05,$05,$07,$07,$05 + .byte $05,$0b,$0d,$05,$07,$01,$01,$05 + .byte $05,$05,$05,$05,$0b,$05,$05,$05 + .byte $05,$05,$0d,$0b,$07,$0b,$0f,$0a + + .byte $0f,$03,$0f,$0f,$0f,$07,$0a,$0e + .byte $0f,$05,$0e,$0b,$0f,$0b,$0f,$0f + .byte $0f,$0b,$0f,$0b,$07,$07,$0e,$0f + .byte $00,$0f,$0d,$0f,$0c,$0b,$03,$03 + .byte $0f,$0b,$05,$00,$07,$0d,$0b,$07 + .byte $0b,$0b,$0b,$0b,$0f,$0f,$0f,$0b + .byte $01,$03,$0d,$0d,$05,$03,$07,$0d + .byte $05,$05,$0b,$0b,$0b,$08,$0b,$0d + .byte $01,$0b,$07,$09,$0d,$0b,$0b,$09 + .byte $07,$0f,$0f,$07,$0b,$05,$03,$0b + .byte $03,$09,$03,$09,$01,$05,$05,$05 + .byte $05,$05,$01,$0b,$0b,$0b,$05,$0b + .byte $0f,$05,$05,$07,$05,$07,$07,$07 + .byte $05,$0b,$0d,$03,$07,$01,$01,$05 + .byte $05,$05,$05,$07,$0b,$05,$05,$05 + .byte $0b,$05,$0b,$0b,$0b,$0b,$0a,$05 + + .byte $09,$03,$0f,$0f,$0f,$07,$0a,$0e + .byte $0f,$0a,$0e,$08,$0f,$08,$03,$0f + .byte $08,$00,$00,$03,$07,$07,$0e,$0f + .byte $0f,$0f,$05,$0f,$0c,$03,$03,$03 + .byte $0f,$0b,$0f,$05,$0b,$0b,$0b,$0f + .byte $0b,$0b,$01,$01,$0f,$01,$0f,$0b + .byte $05,$0b,$0b,$0b,$01,$0d,$03,$0b + .byte $0b,$09,$0f,$0f,$07,$0f,$0d,$0b + .byte $01,$0d,$03,$07,$09,$05,$01,$05 + .byte $03,$03,$0d,$05,$0b,$01,$05,$05 + .byte $05,$05,$05,$07,$0b,$05,$05,$05 + .byte $05,$05,$0d,$0b,$0b,$0b,$05,$00 + .byte $00,$01,$03,$07,$05,$03,$03,$01 + .byte $01,$0b,$0d,$03,$07,$05,$01,$05 + .byte $03,$05,$03,$0b,$0b,$05,$05,$01 + .byte $0b,$0b,$0b,$00,$0b,$0b,$05,$05 + + .byte $09,$03,$00,$0f,$0f,$07,$05,$0e + .byte $05,$05,$0e,$08,$0c,$08,$03,$0f + .byte $08,$00,$00,$03,$07,$07,$0e,$0f + .byte $0f,$0f,$03,$03,$0f,$03,$0f,$0c + .byte $0f,$0f,$0f,$00,$0d,$07,$04,$0f + .byte $0b,$0b,$0b,$0b,$0f,$0f,$0f,$0b + .byte $05,$0b,$07,$0d,$0d,$0d,$05,$0b + .byte $05,$0d,$0f,$0f,$0b,$08,$0b,$0b + .byte $07,$09,$05,$07,$05,$01,$0b,$05 + .byte $05,$0b,$0d,$03,$0b,$01,$05,$05 + .byte $05,$05,$07,$0b,$0b,$05,$05,$01 + .byte $0b,$05,$0b,$0b,$0b,$0b,$0f,$00 + .byte $00,$05,$05,$07,$05,$07,$07,$05 + .byte $05,$0b,$0d,$03,$07,$05,$01,$05 + .byte $07,$05,$03,$0d,$0b,$05,$05,$01 + .byte $0b,$0b,$0b,$00,$07,$0b,$05,$0a + + .byte $0f,$03,$00,$0f,$0f,$07,$05,$0e + .byte $05,$0a,$0e,$0b,$0c,$0f,$0b,$0f + .byte $0b,$0f,$0b,$0b,$07,$07,$0e,$0f + .byte $0f,$00,$03,$03,$0f,$0f,$0f,$0c + .byte $0f,$0f,$0f,$05,$03,$05,$05,$0f + .byte $0b,$0b,$05,$0b,$0b,$0f,$0b,$07 + .byte $05,$0b,$07,$05,$0d,$05,$05,$0b + .byte $05,$05,$0b,$0b,$0b,$0f,$0b,$0f + .byte $05,$05,$05,$07,$05,$07,$0b,$09 + .byte $05,$0b,$0d,$05,$0b,$05,$05,$05 + .byte $03,$09,$07,$0d,$0b,$05,$0b,$01 + .byte $05,$09,$07,$0b,$0d,$0b,$0f,$0b + .byte $0f,$05,$05,$05,$05,$07,$07,$05 + .byte $05,$0b,$05,$05,$07,$05,$05,$05 + .byte $07,$0b,$05,$05,$0b,$05,$0b,$05 + .byte $05,$0b,$07,$0b,$07,$0b,$05,$0a + + .byte $0f,$03,$00,$0f,$0f,$07,$0a,$0e + .byte $0a,$05,$0e,$0b,$0c,$0f,$0b,$00 + .byte $0b,$0f,$0b,$0b,$07,$07,$0e,$0f + .byte $0f,$00,$07,$03,$0f,$0f,$0f,$0c + .byte $0f,$0b,$0f,$05,$0b,$05,$08,$0f + .byte $0d,$07,$0f,$0f,$0b,$0f,$0b,$07 + .byte $0b,$01,$01,$0b,$0d,$0b,$0b,$0b + .byte $0b,$0b,$0f,$0b,$0d,$0f,$07,$0b + .byte $0b,$09,$03,$09,$09,$09,$0b,$0d + .byte $05,$01,$0d,$05,$01,$05,$05,$0b + .byte $07,$0d,$07,$03,$0d,$09,$0b,$05 + .byte $05,$0d,$01,$09,$0d,$03,$0f,$0b + .byte $0f,$05,$03,$0b,$03,$01,$07,$0b + .byte $05,$01,$0b,$05,$01,$05,$05,$0b + .byte $07,$0d,$05,$0b,$0b,$0b,$0b,$05 + .byte $05,$0b,$01,$0b,$0b,$0b,$05,$05 + + .byte $0f,$03,$00,$0f,$00,$07,$0a,$0e + .byte $0a,$0a,$0e,$0b,$0c,$0f,$0b,$00 + .byte $0b,$0f,$0b,$0b,$07,$07,$0e,$0f + .byte $0f,$00,$0f,$03,$0f,$0f,$0f,$0c + .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$07,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$07,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$03 + .byte $0f,$0f,$03,$0f,$0f,$0f,$0f,$0f + .byte $07,$0d,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$03,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f + .byte $0f,$0f,$0f,$0b,$0b,$0b,$0f,$05 diff --git a/libsrc/c64/soft80_color.s b/libsrc/c64/soft80_color.s new file mode 100644 index 000000000..8c1d113ac --- /dev/null +++ b/libsrc/c64/soft80_color.s @@ -0,0 +1,159 @@ +; +; Groepaz/Hitmen, 12.10.2015 +; +; high level implementation for the soft80 implementation +; +; unsigned char __fastcall__ textcolor (unsigned char color); +; unsigned char __fastcall__ bgcolor (unsigned char color); +; + + .export soft80_textcolor, soft80_bgcolor + .import soft80_internal_cellcolor, soft80_internal_bgcolor + .import soft80_internal_cursorxlsb + .import soft80_kplot, soft80_checkchar + + .importzp tmp1, tmp2 + + .include "c64.inc" + .include "soft80.inc" + +soft80_textcolor: + ldx CHARCOLOR ; get old value + sta CHARCOLOR ; set new value + +mkcharcolor: + lda soft80_internal_bgcolor + asl a + asl a + asl a + asl a + sta tmp1 ; remember new bg color (high nibble) + ora CHARCOLOR + sta soft80_internal_cellcolor ; text/bg combo for new chars + + txa ; get old value + rts + +soft80_bgcolor: + ldx soft80_internal_bgcolor ; get old value + stx tmp2 ; save old value + sta soft80_internal_bgcolor ; set new value + + jsr mkcharcolor + + lda CURS_X + pha + lda CURS_Y + pha + + ldy #0 + ldx #0 + clc + jsr soft80_kplot + + sei + lda $01 + pha + ldx #$34 + stx $01 ; $34 + + ;ldy #0 ; is still 0 + + lda #24 + sta CURS_Y +lpy: + lda #39 + sta CURS_X +lpx: + +.if SOFT80COLORVOODOO = 1 + ; if the old bg color is equal to color ram of that cell, then also + ; update the color ram to the new value. + + inc $01 ; $35 + lda (CRAM_PTR),y ; colram + stx $01 ; $34 + + and #$0f + cmp tmp2 ; old bg color + bne @sk1 + + ; if the left character in the cell is not a space, then dont update + ; the color ram + lda #1 + sta soft80_internal_cursorxlsb + jsr soft80_checkchar + bcc @sk1 + lda soft80_internal_bgcolor ; new bg color + + inc $01 ; $35 + sta (CRAM_PTR),y ; colram + stx $01 ; $34 +@sk1: +.endif + ; if the old bg color is equal to text color in this cell, then also + ; update the text color to the new value. + + lda (CRAM_PTR),y ; vram + and #$0f + cmp tmp2 ; old bg color + bne @sk2 + + ; if there are non space characters in the cell, do not update the + ; color ram + pha + lda #0 + sta soft80_internal_cursorxlsb + jsr soft80_checkchar + pla + bcc @sk2 + + pha + inc soft80_internal_cursorxlsb + jsr soft80_checkchar + pla + bcc @sk2 + + lda soft80_internal_bgcolor ; new bg color +@sk2: + ora tmp1 ; new bg color (high nibble) + sta (CRAM_PTR),y ; vram + + inc CRAM_PTR + bne @sk3 + inc CRAM_PTR+1 +@sk3: + + lda SCREEN_PTR + clc + adc #8 + sta SCREEN_PTR + bcc @sk4 + inc SCREEN_PTR+1 +@sk4: + + dec CURS_X + bpl lpx + + dec CURS_Y + bpl lpy + + pla + sta $01 ; enable I/O + cli + + pla ; CURS_Y + tax + pla ; CURS_X + tay + clc + jsr soft80_kplot + + lda tmp2 ; get old value + rts + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import soft80_init +conio_init = soft80_init diff --git a/libsrc/c64/soft80_conio.s b/libsrc/c64/soft80_conio.s new file mode 100644 index 000000000..874d41a53 --- /dev/null +++ b/libsrc/c64/soft80_conio.s @@ -0,0 +1,159 @@ +; +; Groepaz/Hitmen, 11.10.2015 +; +; Low level init code for soft80 screen output/console input +; + + .constructor soft80_init, 8 + .destructor soft80_shutdown + + .import soft80_kclrscr, soft80_charset + .export soft80_internal_bgcolor, soft80_internal_cellcolor + .export soft80_internal_cursorxlsb + + .importzp ptr1, ptr2, ptr3 + + .include "c64.inc" + .include "soft80.inc" + +soft80_init: + lda soft80_first_init + bne @skp + jsr firstinit +@skp: + ; the "color voodoo" in other parts of the code relies on the vram and + ; colorram being set up as expected, which is why we cant use the + ; _bgcolor and _textcolor functions here. + + lda CHARCOLOR ; use current textcolor + and #$0F ; make sure the upper nibble is 0s + sta CHARCOLOR + + lda VIC_BG_COLOR0 ; use current bgcolor + and #$0F + sta soft80_internal_bgcolor + asl a + asl a + asl a + asl a + ora CHARCOLOR + sta soft80_internal_cellcolor + + lda #$3B + sta VIC_CTRL1 + lda #$00 + sta CIA2_PRA + lda #$68 + sta VIC_VIDEO_ADR + lda #$C8 + sta VIC_CTRL2 + + jmp soft80_kclrscr + +soft80_shutdown: + + lda #$07 + sta CIA2_PRA + jmp $FF5B ; Initialize video I/O + + .segment "INIT" +firstinit: + ; copy charset to RAM under I/O + sei + lda $01 + pha + lda #$34 + sta $01 + + inc soft80_first_init + + lda #<soft80_charset + ldx #>soft80_charset + sta ptr1 + stx ptr1+1 + lda #<soft80_lo_charset + ldx #>soft80_lo_charset + sta ptr2 + stx ptr2+1 + lda #<soft80_hi_charset + ldx #>soft80_hi_charset + sta ptr3 + stx ptr3+1 + + ldx #4 +@l2: + ldy #0 +@l1: + lda (ptr1),y + sta (ptr2),y + asl a + asl a + asl a + asl a + sta (ptr3),y + iny + bne @l1 + inc ptr1+1 + inc ptr2+1 + inc ptr3+1 + dex + bne @l2 + + ; copy the kplot tables to ram under I/O + ;ldx #0 ; is 0 +@l3: + lda soft80_tables_data_start,x + sta soft80_bitmapxlo,x + lda soft80_tables_data_start + (soft80_tables_data_end - soft80_tables_data_start - $0100),x + sta soft80_bitmapxlo + (soft80_tables_data_end - soft80_tables_data_start - $0100),x + inx + bne @l3 + + pla + sta $01 + cli + rts + +; the following tables take up 267 bytes, used by kplot +soft80_tables_data_start: + +soft80_bitmapxlo_data: + .repeat 80,col + .byte <((col/2)*8) + .endrepeat +soft80_bitmapxhi_data: + .repeat 80,col + .byte >((col/2)*8) + .endrepeat +soft80_vramlo_data: + .repeat 25,row + .byte <(soft80_vram+(row*40)) + .endrepeat + .byte 0,0,0,0,0,0,0 ; padding to next page +soft80_vramhi_data: + .repeat 25,row + .byte >(soft80_vram+(row*40)) + .endrepeat +soft80_bitmapylo_data: + .repeat 25,row + .byte <(soft80_bitmap+(row*40*8)) + .endrepeat +soft80_bitmapyhi_data: + .repeat 25,row + .byte >(soft80_bitmap+(row*40*8)) + .endrepeat + +soft80_tables_data_end: + +;------------------------------------------------------------------------------- + .segment "INITBSS" +soft80_internal_cellcolor: + .res 1 +soft80_internal_bgcolor: + .res 1 +soft80_internal_cursorxlsb: + .res 1 + + .data +soft80_first_init: + .byte 0 ; flag to check first init, this really must be in .data diff --git a/libsrc/c64/soft80_cputc.s b/libsrc/c64/soft80_cputc.s new file mode 100644 index 000000000..acbe5b560 --- /dev/null +++ b/libsrc/c64/soft80_cputc.s @@ -0,0 +1,522 @@ +; +; Groepaz/Hitmen, 11.10.2015 +; +; high level implementation for the soft80 implementation +; +; void cputcxy (unsigned char x, unsigned char y, char c); +; void cputc (char c); +; + + .export soft80_cputcxy, soft80_cputc + .export soft80_cputdirect, soft80_putchar + .export soft80_newline, soft80_plot + .export soft80_checkchar + + .import popa, _gotoxy + + .import soft80_kplot + .import soft80_internal_bgcolor, soft80_internal_cellcolor + .import soft80_internal_cursorxlsb + + .importzp tmp4,tmp3 + + .include "c64.inc" + .include "soft80.inc" + +soft80_cputcxy: + pha ; Save C + jsr popa ; Get Y + jsr _gotoxy ; Set cursor, drop x + pla ; Restore C + +; Plot a character - also used as internal function + +soft80_cputc: + cmp #$0A ; CR? + bne L1 + + lda #0 + sta CURS_X + + ; Set cursor position, calculate RAM pointers +soft80_plot: + ldx CURS_Y + ldy CURS_X + clc + jmp soft80_kplot ; Set the new cursor + +L1: cmp #$0D ; LF? + beq soft80_newline ; Recalculate pointers + + ; shortcut for codes < $80 ... codes $20-$7f can be printed directly, + ; codes $00-$1f are control codes which are not printable and thus may + ; give undefined result. + tay + bpl @L10 + + ; codes $80-$ff must get converted like this: + ; $80-$9f -> dont care (control codes) + ; $a0-$bf -> $00-$1f + ; $c0-$df -> $60-$7f + ; $e0-$ff -> $00-$1f + + ora #%01000000 ; $40 + clc + adc #%00100000 ; $20 + and #%01111111 ; $7f +@L10: + + ; entry point for direct output of a character. the value passed in + ; akku must match the offset in the charset. + ; - the following may not modify tmp1 +soft80_cputdirect: + jsr soft80_putchar ; Write the character to the screen + + ; Advance cursor position + iny ; contains CURS_X + cpy #charsperline + beq @L3 + + sty CURS_X + tya + and #$01 + sta soft80_internal_cursorxlsb + bne @L5 + + lda SCREEN_PTR + clc + adc #8 + sta SCREEN_PTR + bcc @L4 + inc SCREEN_PTR+1 +@L4: + inc CRAM_PTR + bne @L5 + inc CRAM_PTR+1 +@L5: + rts +@L3: + inc CURS_Y ; new line + ldy #0 ; + cr + sty CURS_X + jmp soft80_plot + + ; - the following may not modify tmp1 +soft80_newline: + + lda SCREEN_PTR + clc + adc #<(40*8) + sta SCREEN_PTR + + lda SCREEN_PTR+1 + adc #>(40*8) + sta SCREEN_PTR+1 + + lda CRAM_PTR + clc + adc #40 + sta CRAM_PTR + bcc @L5 + inc CRAM_PTR+1 +@L5: + inc CURS_Y + rts + +;------------------------------------------------------------------------------- +; All following code belongs to the character output to bitmap +; +; this stuff is going to be used a lot so we unroll it a bit for speed +;------------------------------------------------------------------------------- + +.if SOFT80FASTSPACE = 1 + +; output inverted space (odd) +draw_spaceinvers_odd: + .repeat 8,line + lda (SCREEN_PTR),y + and #$f0 + sta (SCREEN_PTR),y + .if line < 7 + iny + .endif + .endrepeat + jmp draw_back + +; output inverted space (general entry point) +; in: y must be $00 +draw_spaceinvers: + +.if SOFT80COLORVOODOO = 1 + jsr soft80_putcolor +.else + lda soft80_internal_cellcolor + sta (CRAM_PTR),y ; vram +.endif + + lda soft80_internal_cursorxlsb + bne draw_spaceinvers_odd + +; output inverted space (even) + .repeat 8,line + lda (SCREEN_PTR),y + and #$0f + sta (SCREEN_PTR),y + .if line < 7 + iny + .endif + .endrepeat + jmp draw_back + +; output space (odd) +draw_space_odd: + .repeat 8,line + lda (SCREEN_PTR),y + ora #$0f + sta (SCREEN_PTR),y + .if line < 7 + iny + .endif + .endrepeat + jmp draw_back + +; output space (general entry point) +; in: y must be $00 +draw_space: + + lda RVS + bne draw_spaceinvers + +.if SOFT80COLORVOODOO = 1 + jsr remcolor +.endif + ;ldy #$00 ; is still $00 + + lda soft80_internal_cursorxlsb + bne draw_space_odd + +; output space (even) + .repeat 8,line + lda (SCREEN_PTR),y + ora #$f0 + sta (SCREEN_PTR),y + .if (line < 7) + iny + .endif + .endrepeat + jmp draw_back +.endif + +;------------------------------------------------------------------------------- +; output one character in internal encoding without advancing cursor position +; generic entry point +; +; - the following may not modify tmp1 +; in: A: charcode +; out: Y: CURS_X +; +soft80_putchar: + sta tmp3 ; remember charcode + + sei + ldx $01 + stx tmp4 + ldx #$34 + + stx $01 ; will stay $34 for space + ldy #$00 ; will be $00 from now on + +.if SOFT80FASTSPACE = 1 + cmp #' ' ; space is a special (optimized) case + beq draw_space +.endif + +.if SOFT80COLORVOODOO = 1 + jsr soft80_putcolor +.else + lda soft80_internal_cellcolor + sta (CRAM_PTR),y ; vram +.endif + +; output character + ldx tmp3 ; get charcode + + lda RVS + beq @skp + jmp draw_charinvers +@skp: + lda soft80_internal_cursorxlsb + bne draw_char_even + +; output character (odd) + .repeat 8,line + lda (SCREEN_PTR),y + and #$0f + ora soft80_hi_charset+(line*$80),x + sta (SCREEN_PTR),y + .if line < 7 + iny + .endif + .endrepeat + jmp draw_back + +; output character (even) +draw_char_even: + .repeat 8,line + lda (SCREEN_PTR),y + and #$f0 + ora soft80_lo_charset+(line*$80),x + sta (SCREEN_PTR),y + .if line < 7 + iny + .endif + .endrepeat + +draw_back: + lda tmp4 + sta $01 + cli + + ldy CURS_X + rts + +; output inverted character (odd) +draw_charinvers_odd: + .repeat 8,line + lda (SCREEN_PTR),y + ora #$0f + eor soft80_lo_charset+(line*$80),x + sta (SCREEN_PTR),y + .if line < 7 + iny + .endif + .endrepeat + jmp draw_back + +; output inverted character (generic) +draw_charinvers: + lda soft80_internal_cursorxlsb + bne draw_charinvers_odd + + .repeat 8,line + lda (SCREEN_PTR),y + ora #$f0 + eor soft80_hi_charset+(line*$80),x + sta (SCREEN_PTR),y + .if line < 7 + iny + .endif + .endrepeat + jmp draw_back + +;------------------------------------------------------------------------------- +; optional "color voodoo". the problem is that each 8x8 cell can only contain +; two colors, one of which is used for the background color, so two characters +; have to share the same text color. +; +; - in a cell that contains two spaces, both the color ram and the text color +; in vram contain the background color +; +; - in a cell that contains one character, its text color goes into vram. the +; color ram contains the background color. +; +; - in a cell that contains two characters, the color of the left character goes +; to vram (and is shared by both for display). the "would be" color of the +; right character goes to color ram as a reminder and can be restored when one +; of the two characters is cleared by a space. + +.if SOFT80COLORVOODOO = 1 + +; remove color from cell, called before putting a "space" character to the bitmap +; +; __ -> __ - +; _A -> _A - +; B_ -> B_ - +; _A -> __ vram = bgcol +; B_ -> __ vram = bgcol +; BA -> _A vram = colram, colram = bgcol +; BA -> B_ colram = bgcol +; +; in: x must be $34 +; y must be $00 +; out: x = $34 +; y = $00 +remcolor: + + ;ldy #$00 ; is still $00 + + ; if the textcolor in vram is equal to the background color, then + ; no (visible) character is in the current cell and we can exit + ; immediately. + lda (CRAM_PTR),y ; vram (textcolor) + and #$0f + cmp soft80_internal_bgcolor + beq @sk1 ; yes, vram==bgcolor + + ; now check if the textcolor in color ram is equal the background color, + ; if yes then there is only one (visible) character in the current cell + inc $01 ; $35 + lda (CRAM_PTR),y ; colram (2nd textcolor) + stx $01 ; $34 + and #$0f + cmp soft80_internal_bgcolor + beq @sk2 ; yes, colram==bgcolor + sta tmp3 ; A contains colram + + ; two characters in the current cell, of which one will get removed + + lda soft80_internal_cursorxlsb + bne @sk3 + + ; vram = colram + lda (CRAM_PTR),y ; vram + and #$f0 + ora tmp3 ; colram value + sta (CRAM_PTR),y ; vram +@sk3: + ; colram = bgcolor + lda soft80_internal_bgcolor + inc $01 ; $35 + sta (CRAM_PTR),y ; colram + stx $01 ; $34 + + rts + +@sk2: + ; colram is bgcolor + ; => only one char in cell used + + jsr soft80_checkchar + bcs @sk1 ; space at current position + + ; vram (textcolor) = bgcolor + lda (CRAM_PTR),y ; vram + and #$f0 + ora soft80_internal_bgcolor + sta (CRAM_PTR),y ; vram +@sk1: + rts + +; put color to cell +; +; __ -> _A vram = textcol +; __ -> B_ vram = textcol +; _A -> BA colram = vram, vram = textcol +; B_ -> BA colram = textcol +; +; _A -> _C vram = textcol +; B_ -> C_ vram = textcol +; BA -> BC colram = textcol +; BA -> CA vram = textcol +; +; in: $01 is $34 (RAM under I/O) when entering +; x must be $34 +; y must be $00 +; out: x = $34 +; y = $00 +soft80_putcolor: + + ;ldy #$00 ; is still $00 + + lda (CRAM_PTR),y ; vram + and #$0f + cmp soft80_internal_bgcolor + beq @sk1 ; vram==bgcolor => first char in cell + + ; vram!=bgcolor => second char in cell + + inc $01 ; $35 + lda (CRAM_PTR),y ; colram + stx $01 ; $34 + and #$0f + cmp soft80_internal_bgcolor + beq @l2s ; colram==bgcolor -> second char in cell + + ; botch characters in the cell are used + + lda soft80_internal_cursorxlsb + bne @sk2 ; jump if odd xpos + + ; vram = textcol + lda soft80_internal_cellcolor + sta (CRAM_PTR),y ; vram + rts + +@l2s: + ; one character in cell is already used + jsr soft80_checkchar + bcc @sk1 ; char at current position => overwrite 1st + + lda soft80_internal_cursorxlsb + beq @sk3 ; jump if even xpos +@sk2: + ; colram = textcol + lda CHARCOLOR + inc $01 ; $35 + sta (CRAM_PTR),y ; colram + stx $01 ; $34 + rts + +@sk3: + ; colram=vram + lda (CRAM_PTR),y ; vram + inc $01 ; $35 + sta (CRAM_PTR),y ; colram + stx $01 ; $34 +@sk1: + ; vram = textcol + lda soft80_internal_cellcolor + sta (CRAM_PTR),y ; vram + rts + +; +; test if there is a space or a character at current position +; +; in: x = $34 +; $01 must be $34 +; +; out: SEC: space +; CLC: character +; x = $34 +; y = $00 +soft80_checkchar: + + lda soft80_internal_cursorxlsb + bne @l1a + + ; check charset data from bottom up, since a lot of eg lowercase chars + ; have no data in the top rows, but all of them DO have data in the + ; second to bottom row, this will likely be faster in average. + + ldy #7 + .repeat 8,line + lda (SCREEN_PTR),y + and #$f0 + cmp #$f0 + bne @ischar + .if (line < 7) + dey + .endif + .endrepeat + ;ldy #$00 ; is 0 + ;sec ; is set + rts +@ischar: + ldy #$00 + ;clc ; is cleared + rts +@l1a: + ldy #$07 + .repeat 8,line + lda (SCREEN_PTR),y + and #$0f + cmp #$0f + bne @ischar + .if line < 7 + dey + .endif + .endrepeat + ;ldy #$00 ; is 0 + ;sec ; is set + rts +.endif diff --git a/libsrc/c64/soft80_kclrscr.s b/libsrc/c64/soft80_kclrscr.s new file mode 100644 index 000000000..7c313afcf --- /dev/null +++ b/libsrc/c64/soft80_kclrscr.s @@ -0,0 +1,76 @@ +; +; Groepaz/Hitmen, 12.10.2015 +; +; lowlevel kclrscr for soft80 implementation +; + + .export soft80_kclrscr + .import soft80_kplot + .import soft80_internal_bgcolor, soft80_internal_cellcolor + .importzp ptr1 + + .include "c64.inc" + .include "soft80.inc" + +soft80_kclrscr: + + lda #<soft80_bitmap + sta ptr1 + lda #>soft80_bitmap + sta ptr1+1 + + lda #$ff + + ldx #$1f +@lp2: + ldy #0 +@lp1: + sta (ptr1),y + iny + bne @lp1 + inc ptr1+1 + dex + bne @lp2 + + ;ldx #$00 +@lp3: + sta soft80_bitmap+$1e40,x + inx + bne @lp3 + +.if SOFT80COLORVOODOO = 1 + lda soft80_internal_bgcolor + jsr clear ; clear color ram +.endif + + sei + ldy $01 + lda #$34 ; enable RAM under I/O + sta $01 + + lda soft80_internal_cellcolor + and #$f0 + ora soft80_internal_bgcolor + jsr clear ; clear vram + + sty $01 + cli + + ldx #0 + ldy #0 + clc + jmp soft80_kplot + + ; clear loop for colram and vram +clear: + ;ldx #$00 +@lp1: + sta soft80_colram,x + sta soft80_colram+$100,x + sta soft80_colram+$200,x + sta soft80_colram+$2e8,x + inx + bne @lp1 + rts + + diff --git a/libsrc/c64/soft80_kplot.s b/libsrc/c64/soft80_kplot.s new file mode 100644 index 000000000..bd52ee6d3 --- /dev/null +++ b/libsrc/c64/soft80_kplot.s @@ -0,0 +1,63 @@ + +; +; Groepaz/Hitmen, 12.10.2015 +; +; lowlevel kplot function for the soft80 implementation +; + + .export soft80_kplot + .import soft80_internal_cursorxlsb + + .include "c64.inc" + .include "soft80.inc" + +soft80_kplot: + bcs @getpos + + stx CURS_Y + sty CURS_X + + sei + lda $01 + pha + lda #$34 ; enable RAM under I/O + sta $01 + + ; calc pointer to bitmap + lda soft80_bitmapylo,x + clc + adc soft80_bitmapxlo,y + sta SCREEN_PTR + lda soft80_bitmapyhi,x + adc soft80_bitmapxhi,y + sta SCREEN_PTR+1 + + tya + and #1 + sta soft80_internal_cursorxlsb + + ; calc pointer to vram + tya + lsr a + + clc + adc soft80_vramlo,x + sta CRAM_PTR + lda #0 + adc soft80_vramhi,x + sta CRAM_PTR+1 + + pla + sta $01 + cli + +@getpos: + ldx CURS_Y + ldy CURS_X + rts + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import soft80_init +conio_init = soft80_init diff --git a/libsrc/c64/soft80_scrsize.s b/libsrc/c64/soft80_scrsize.s new file mode 100644 index 000000000..9f1701a9a --- /dev/null +++ b/libsrc/c64/soft80_scrsize.s @@ -0,0 +1,14 @@ +; +; Groepaz/Hitmen, 12.10.2015 +; +; lowlevel screensize function for the soft80 implementation +; + + .export soft80_screensize + + .include "soft80.inc" + +soft80_screensize: + ldy #screenrows + ldx #charsperline + rts diff --git a/libsrc/c64/soft80mono_cgetc.s b/libsrc/c64/soft80mono_cgetc.s new file mode 100644 index 000000000..d99dc7775 --- /dev/null +++ b/libsrc/c64/soft80mono_cgetc.s @@ -0,0 +1,66 @@ +; +; Groepaz/Hitmen, 19.10.2015 +; +; high level implementation for the monochrome soft80 implementation +; +; char cgetc (void); +; + + .export soft80mono_cgetc + .import soft80mono_internal_cellcolor, soft80mono_internal_cursorxlsb + .import soft80mono_internal_nibble + .import cursor + .importzp tmp1 + + .include "c64.inc" + .include "soft80.inc" + +soft80mono_cgetc: + lda KEY_COUNT ; Get number of characters + bne @L3 ; Jump if there are already chars waiting + + jsr invertcursor ; set cursor on or off accordingly + +@L1: lda KEY_COUNT ; wait for key + beq @L1 + + jsr invertcursor ; set cursor on or off accordingly + +@L3: jsr KBDREAD ; Read char and return in A + ldx #0 + rts + +; Switch the cursor on or off (invert) + +invertcursor: + lda cursor + bne @invert + rts +@invert: + + sei + lda $01 ; enable RAM under I/O + pha + lda #$34 + sta $01 + + ldy #$00 + ldx soft80mono_internal_cursorxlsb +@lp1: + lda (SCREEN_PTR),y + eor soft80mono_internal_nibble,x + sta (SCREEN_PTR),y + iny + cpy #8 + bne @lp1 + + pla + sta $01 ; enable I/O + cli + rts + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import soft80mono_init +conio_init = soft80mono_init diff --git a/libsrc/c64/soft80mono_color.s b/libsrc/c64/soft80mono_color.s new file mode 100644 index 000000000..aa24957d5 --- /dev/null +++ b/libsrc/c64/soft80mono_color.s @@ -0,0 +1,65 @@ +; +; Groepaz/Hitmen, 19.10.2015 +; +; high level implementation for the monochrome soft80 implementation +; +; unsigned char __fastcall__ textcolor (unsigned char color); +; unsigned char __fastcall__ bgcolor (unsigned char color); +; + + .export soft80mono_textcolor, soft80mono_bgcolor + .import soft80mono_internal_cellcolor, soft80mono_internal_bgcolor + + .importzp tmp1 + + .include "c64.inc" + .include "soft80.inc" + +soft80mono_textcolor: + ldx CHARCOLOR ; get old value + stx tmp1 ; save old value + sta CHARCOLOR ; set new value + +mkcharcolor: + lda soft80mono_internal_bgcolor + asl a + asl a + asl a + asl a + ora CHARCOLOR + sta soft80mono_internal_cellcolor ; text/bg combo for new chars + + sei + ldy $01 + lda #$34 ; enable RAM under I/O + sta $01 + + lda soft80mono_internal_cellcolor + ; clear loop for vram + ldx #$00 +@lp1: + sta soft80_vram,x + sta soft80_vram+$100,x + sta soft80_vram+$200,x + sta soft80_vram+$2e8,x + inx + bne @lp1 + + sty $01 + cli + + lda tmp1 ; get old value + rts + +soft80mono_bgcolor: + ldx soft80mono_internal_bgcolor ; get old value + stx tmp1 ; save old value + sta soft80mono_internal_bgcolor ; set new value + + jmp mkcharcolor + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import soft80mono_init +conio_init = soft80mono_init diff --git a/libsrc/c64/soft80mono_conio.s b/libsrc/c64/soft80mono_conio.s new file mode 100644 index 000000000..759b280c6 --- /dev/null +++ b/libsrc/c64/soft80mono_conio.s @@ -0,0 +1,168 @@ +; +; Groepaz/Hitmen, 19.10.2015 +; +; Low level init code for the monochrome soft80 screen output/console input +; + + .constructor soft80mono_init, 8 + .destructor soft80mono_shutdown + + .import soft80mono_kclrscr, soft80_charset + .export soft80mono_internal_bgcolor, soft80mono_internal_cellcolor + .export soft80mono_internal_cursorxlsb + .export soft80mono_internal_nibble + + .importzp ptr1, ptr2, ptr3 + + .include "c64.inc" + .include "soft80.inc" + +soft80mono_init: + lda soft80mono_first_init + bne @skp + jsr firstinit +@skp: + ; the "color voodoo" in other parts of the code relies on the vram and + ; colorram being set up as expected, which is why we cant use the + ; _bgcolor and _textcolor functions here. + + lda CHARCOLOR ; use current textcolor + and #$0f ; make sure the upper nibble is 0s + sta CHARCOLOR + + lda VIC_BG_COLOR0 ; use current bgcolor + and #$0f + sta soft80mono_internal_bgcolor + asl a + asl a + asl a + asl a + ora CHARCOLOR + sta soft80mono_internal_cellcolor + + lda #$3b + sta VIC_CTRL1 + lda #$00 + sta CIA2_PRA + lda #$68 + sta VIC_VIDEO_ADR + lda #$c8 + sta VIC_CTRL2 + + jmp soft80mono_kclrscr + +soft80mono_shutdown: + lda #$1b + sta VIC_CTRL1 + lda #$03 + sta CIA2_PRA + lda #$15 + sta VIC_VIDEO_ADR + rts + + .segment "INIT" +firstinit: + ; copy charset to RAM under I/O + sei + lda $01 + pha + lda #$34 + sta $01 + + inc soft80mono_first_init + + lda #>soft80_charset + sta ptr1+1 + lda #<soft80_charset + sta ptr1 + lda #>soft80_lo_charset + sta ptr2+1 + lda #<soft80_lo_charset + sta ptr2 + lda #>soft80_hi_charset + sta ptr3+1 + lda #<soft80_hi_charset + sta ptr3 + + ldx #4 +@l2: + ldy #0 +@l1: + lda (ptr1),y + sta (ptr2),y + asl a + asl a + asl a + asl a + sta (ptr3),y + iny + bne @l1 + inc ptr1+1 + inc ptr2+1 + inc ptr3+1 + dex + bne @l2 + + ; copy the kplot tables to ram under I/O + ;ldx #0 ; is 0 +@l3: + lda soft80_tables_data_start,x + sta soft80_bitmapxlo,x + lda soft80_tables_data_start + (soft80_tables_data_end - soft80_tables_data_start - $100) ,x + sta soft80_bitmapxlo + (soft80_tables_data_end - soft80_tables_data_start - $100),x + inx + bne @l3 + + pla + sta $01 + cli + rts + +; the following tables take up 267 bytes, used by kplot +soft80_tables_data_start: + +soft80_bitmapxlo_data: + .repeat 80,col + .byte <((col/2)*8) + .endrepeat +soft80_bitmapxhi_data: + .repeat 80,col + .byte >((col/2)*8) + .endrepeat +soft80_vramlo_data: + .repeat 25,row + .byte <(soft80_vram+(row*40)) + .endrepeat + .byte 0,0,0,0,0,0,0 ; padding to next page +soft80_vramhi_data: + .repeat 25,row + .byte >(soft80_vram+(row*40)) + .endrepeat +soft80_bitmapylo_data: + .repeat 25,row + .byte <(soft80_bitmap+(row*40*8)) + .endrepeat +soft80_bitmapyhi_data: + .repeat 25,row + .byte >(soft80_bitmap+(row*40*8)) + .endrepeat + +soft80_tables_data_end: + +;------------------------------------------------------------------------------- + .segment "INITBSS" +soft80mono_internal_cellcolor: + .res 1 +soft80mono_internal_bgcolor: + .res 1 +soft80mono_internal_cursorxlsb: + .res 1 + + .data +soft80mono_first_init: + .byte 0 ; flag to check first init, this really must be in .data + + .rodata +soft80mono_internal_nibble: + .byte $f0, $0f + diff --git a/libsrc/c64/soft80mono_cputc.s b/libsrc/c64/soft80mono_cputc.s new file mode 100644 index 000000000..c89362cb5 --- /dev/null +++ b/libsrc/c64/soft80mono_cputc.s @@ -0,0 +1,205 @@ +; +; Groepaz/Hitmen, 19.10.2015 +; +; high level implementation for the monochrome soft80 implementation +; +; void cputcxy (unsigned char x, unsigned char y, char c); +; void cputc (char c); +; + + .export soft80mono_cputcxy, soft80mono_cputc + .export soft80mono_cputdirect, soft80mono_putchar + .export soft80mono_newline, soft80mono_plot + + .import popa, _gotoxy + + .import soft80mono_kplot + .import soft80mono_internal_bgcolor, soft80mono_internal_cellcolor + .import soft80mono_internal_cursorxlsb, soft80mono_internal_nibble + + .importzp tmp4, tmp3, ptr2 + + .include "c64.inc" + .include "soft80.inc" + +soft80mono_cputcxy: + pha ; Save C + jsr popa ; Get Y + jsr _gotoxy ; Set cursor, drop x + pla ; Restore C + +; Plot a character - also used as internal function + +soft80mono_cputc: + cmp #$0A ; CR? + bne L1 + + lda #0 + sta CURS_X + + ; Set cursor position, calculate RAM pointers +soft80mono_plot: + ldx CURS_Y + ldy CURS_X + clc + jmp soft80mono_kplot ; Set the new cursor + +L1: cmp #$0D ; LF? + beq soft80mono_newline ; Recalculate pointers + + ; shortcut for codes < $80 ... codes $20-$7f can be printed directly, + ; codes $00-$1f are control codes which are not printable and thus may + ; give undefined result. + tay + bpl @L10 + + ; codes $80-$ff must get converted like this: + ; $80-$9f -> dont care (control codes) + ; $a0-$bf -> $00-$1f + ; $c0-$df -> $60-$7f + ; $e0-$ff -> $00-$1f + + ora #%01000000 ; $40 + clc + adc #%00100000 ; $20 + and #%01111111 ; $7f +@L10: + + ; entry point for direct output of a character. the value passed in + ; akku must match the offset in the charset. + ; - the following may not modify tmp1 +soft80mono_cputdirect: + jsr soft80mono_putchar ; Write the character to the screen + + ; Advance cursor position + iny ; contains CURS_X + cpy #charsperline + beq @L3 + + sty CURS_X + tya + and #$01 + sta soft80mono_internal_cursorxlsb + bne @L4 + + lda SCREEN_PTR + clc + adc #8 + sta SCREEN_PTR + bcc @L4 + inc SCREEN_PTR+1 +@L4: + rts +@L3: + inc CURS_Y ; new line + ldy #0 ; + cr + sty CURS_X + jmp soft80mono_plot + + ; - the following may not modify tmp1 +soft80mono_newline: + + lda SCREEN_PTR + clc + adc #<(40*8) + sta SCREEN_PTR + + lda SCREEN_PTR+1 + adc #>(40*8) + sta SCREEN_PTR+1 + + inc CURS_Y + rts + +;------------------------------------------------------------------------------- +; output one character in internal encoding without advancing cursor position +; generic entry point +; +; - the following may not modify tmp1 +; in: A: charcode +; out: Y: CURS_X +; +soft80mono_putchar: + sta tmp3 ; save charcode + + sei + lda $01 + pha + lda #$34 + sta $01 ; enable RAM under I/O + + ldy #$00 ; will be $00 from now on + + ldx soft80mono_internal_cursorxlsb + lda chardatal,x + clc + adc tmp3 + sta ptr2 + lda chardatah,x + adc #0 + sta ptr2+1 + + lda RVS + bne draw_charinvers + + lda nibble,x + sta tmp3 + + ;ldy #0 ; is still $00 +@lp1: + lda (SCREEN_PTR),y + and tmp3 + ora (ptr2),y + sta (SCREEN_PTR),y + clc + lda ptr2 + adc #$7f + sta ptr2 + bcc @sk1 + inc ptr2+1 +@sk1: + iny + cpy #8 + bne @lp1 + +draw_back: + pla + sta $01 + cli + + ldy CURS_X + rts + +; output inverted character +draw_charinvers: + lda soft80mono_internal_nibble,x + sta tmp3 + + ;ldy #0 ; is still $00 +@lp1: + lda (SCREEN_PTR),y + ora tmp3 + eor (ptr2),y + sta (SCREEN_PTR),y + clc + lda ptr2 + adc #$7f + sta ptr2 + bcc @sk1 + inc ptr2+1 +@sk1: + iny + cpy #8 + bne @lp1 + jmp draw_back + + .rodata +chardatal: + .byte <soft80_hi_charset + .byte <soft80_lo_charset +chardatah: + .byte >soft80_hi_charset + .byte >soft80_lo_charset +nibble: + .byte $0f, $f0 + diff --git a/libsrc/c64/soft80mono_kclrscr.s b/libsrc/c64/soft80mono_kclrscr.s new file mode 100644 index 000000000..99243c699 --- /dev/null +++ b/libsrc/c64/soft80mono_kclrscr.s @@ -0,0 +1,63 @@ +; +; Groepaz/Hitmen, 19.10.2015 +; +; lowlevel kclrscr for the monochrome soft80 implementation +; + + .export soft80mono_kclrscr + .import soft80mono_kplot + .import soft80mono_internal_bgcolor, soft80mono_internal_cellcolor + .importzp ptr1 + + .include "c64.inc" + .include "soft80.inc" + +soft80mono_kclrscr: + + lda #<soft80_bitmap + sta ptr1 + lda #>soft80_bitmap + sta ptr1+1 + + lda #$ff + + ldx #$1f +@lp2: + ldy #0 +@lp1: + sta (ptr1),y + iny + bne @lp1 + inc ptr1+1 + dex + bne @lp2 + + ;ldx #$00 +@lp3: + sta soft80_bitmap+$1e40,x + inx + bne @lp3 + + sei + ldy $01 + lda #$34 ; enable RAM under I/O + sta $01 + + lda soft80mono_internal_cellcolor + ; clear loop for vram + ;ldx #$00 +@lp4: + sta soft80_vram,x + sta soft80_vram+$100,x + sta soft80_vram+$200,x + sta soft80_vram+$2e8,x + inx + bne @lp4 + + sty $01 + cli + + ldx #0 + ldy #0 + clc + jmp soft80mono_kplot diff --git a/libsrc/c64/soft80mono_kplot.s b/libsrc/c64/soft80mono_kplot.s new file mode 100644 index 000000000..b987924f3 --- /dev/null +++ b/libsrc/c64/soft80mono_kplot.s @@ -0,0 +1,52 @@ + +; +; Groepaz/Hitmen, 19.10.2015 +; +; lowlevel kplot function for the monochrome soft80 implementation +; + + .export soft80mono_kplot + .import soft80mono_internal_cursorxlsb + + .include "c64.inc" + .include "soft80.inc" + +soft80mono_kplot: + bcs @getpos + + stx CURS_Y + sty CURS_X + + sei + lda $01 + pha + lda #$34 ; enable RAM under I/O + sta $01 + + ; calc pointer to bitmap + lda soft80_bitmapylo,x + clc + adc soft80_bitmapxlo,y + sta SCREEN_PTR + lda soft80_bitmapyhi,x + adc soft80_bitmapxhi,y + sta SCREEN_PTR+1 + + tya + and #1 + sta soft80mono_internal_cursorxlsb + + pla + sta $01 + cli + +@getpos: + ldx CURS_Y + ldy CURS_X + rts + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import soft80mono_init +conio_init = soft80mono_init diff --git a/libsrc/c64/systime.s b/libsrc/c64/systime.s index a00df1397..f8cd1b714 100644 --- a/libsrc/c64/systime.s +++ b/libsrc/c64/systime.s @@ -63,6 +63,7 @@ BCD2dec:tax ; Constructor that writes to the 1/10 sec register of the TOD to kick it ; into action. If this is not done, the clock hangs. We will read the register ; and write it again, ignoring a possible change in between. +.segment "INIT" .proc initsystime @@ -81,7 +82,6 @@ BCD2dec:tax .endproc - ;---------------------------------------------------------------------------- ; TM struct with date set to 1970-01-01 .data @@ -95,4 +95,3 @@ TM: .word 0 ; tm_sec .word 0 ; tm_wday .word 0 ; tm_yday .word 0 ; tm_isdst - diff --git a/libsrc/cbm/cbm_load.c b/libsrc/cbm/cbm_load.c index 695af504b..c1c6f568a 100644 --- a/libsrc/cbm/cbm_load.c +++ b/libsrc/cbm/cbm_load.c @@ -1,9 +1,9 @@ /* ** Marc 'BlackJack' Rintsch, 06.03.2001 ** -** unsigned int cbm_load(const char* name, -** unsigned char device, -** const unsigned char* data); +** unsigned int __fastcall__ cbm_load(const char* name, +** unsigned char device, +** const unsigned char* data); */ #include <cbm.h> @@ -11,7 +11,7 @@ /* loads file "name" from given device to given address or to the load address ** of the file if "data" is 0 */ -unsigned int cbm_load(const char* name, unsigned char device, void* data) +unsigned int __fastcall__ cbm_load(const char* name, unsigned char device, void* data) { /* LFN is set to 0; but, it's not needed for loading ** (BASIC V2 sets it to the value of the SA for LOAD). diff --git a/libsrc/cbm/chline.s b/libsrc/cbm/chline.s index 26603b2fe..fe7e7255d 100644 --- a/libsrc/cbm/chline.s +++ b/libsrc/cbm/chline.s @@ -7,7 +7,7 @@ .export _chlinexy, _chline .import popa, _gotoxy, cputdirect - .importzp tmp1 + .importzp tmp1, chlinechar _chlinexy: pha ; Save the length @@ -19,7 +19,7 @@ _chline: cmp #0 ; Is the length zero? beq L9 ; Jump if done sta tmp1 -L1: lda #64 ; Horizontal line, screen code +L1: lda #chlinechar ; Horizontal line, screen code jsr cputdirect ; Direct output dec tmp1 bne L1 diff --git a/libsrc/cbm/clinechars.s b/libsrc/cbm/clinechars.s new file mode 100644 index 000000000..54896574b --- /dev/null +++ b/libsrc/cbm/clinechars.s @@ -0,0 +1,6 @@ +; +; Chars used by chline () and cvline () +; + + .exportzp chlinechar = 64 + .exportzp cvlinechar = 93 diff --git a/libsrc/cbm/cvline.s b/libsrc/cbm/cvline.s index f310e4322..2cf231e98 100644 --- a/libsrc/cbm/cvline.s +++ b/libsrc/cbm/cvline.s @@ -7,7 +7,7 @@ .export _cvlinexy, _cvline .import popa, _gotoxy, putchar, newline - .importzp tmp1 + .importzp tmp1, cvlinechar _cvlinexy: pha ; Save the length @@ -19,7 +19,7 @@ _cvline: cmp #0 ; Is the length zero? beq L9 ; Jump if done sta tmp1 -L1: lda #93 ; Vertical bar +L1: lda #cvlinechar ; Vertical bar jsr putchar ; Write, no cursor advance jsr newline ; Advance cursor to next line dec tmp1 diff --git a/libsrc/cbm/exec.c b/libsrc/cbm/exec.c index 36c3afe00..b9c1bdc96 100644 --- a/libsrc/cbm/exec.c +++ b/libsrc/cbm/exec.c @@ -1,7 +1,7 @@ /* ** Program-chaining function for Commodore platforms. ** -** 2013-09-04, Greg King +** 2015-09-27, Greg King ** ** This function exploits the program-chaining feature in CBM BASIC's ROM. ** @@ -32,42 +32,46 @@ /* The struct below is a line of BASIC code. It sits in the LOWCODE segment ** to make sure that it won't be hidden by a ROM when BASIC is re-enabled. ** The line is: -** 0 LOAD""+"" ,01 +** 0 CLR:LOAD""+"" ,01 ** After this function has written into the line, it might look like this: -** 0 LOAD""+"program name" ,08 +** 0 CLR:LOAD""+"program name" ,08 ** ** When BASIC's LOAD command asks the Kernal to load a file, it gives the ** Kernal a pointer to a file-name string. CC65's CBM programs use that ** pointer to give a copy of the program's name to main()'s argv[0] parameter. -** But, when BASIC uses a string literal that's in a program, it points +** But, when BASIC uses a string literal that is in a program, it points ** directly to that literal -- in the models that don't use banked RAM ** (Pet/CBM, VIC-20, and 64). The literal is overwritten by the next program -** that's loaded. So, argv[0] would point to machine code. String operations +** that is loaded. So, argv[0] would point to machine code. String operations ** create a new result string -- even when that operation changes nothing. The ** result is put in the string space at the top of BASIC's memory. So, the ""+ ** in this BASIC line guarantees that argv[0] will get a name from a safe place. */ #pragma data-name(push, "LOWCODE") static struct line { - const char end_of_line; - const struct line *const next; + const char end_of_line; /* fake previous line */ + const struct line* const next; const unsigned line_num; - const char load_token, quotes[2], add_token, quote; + const char CLR_token, colon, LOAD_token, quotes[2], add_token, quote; char name[21]; const char comma; char unit[3]; } basic = { - '\0', &basic + 1, /* high byte of link must be non-zero */ - 0, 0x93, "\"\"", 0xaa, '\"', - "\" ", /* format: "123:1234567890123456\"" */ + '\0', &basic + 1, /* high byte of link must be non-zero */ + 0, 0x9C, ':', 0x93, "\"\"", 0xAA, '\"', + "\" ", /* format: "123:1234567890123456\"" */ ',', "01" }; #pragma data-name(pop) /* These values are platform-specific. */ -extern const struct line *txtptr; +extern const void* vartab; /* points to BASIC program variables */ +#pragma zpsym("vartab") +extern const void* memsize; /* points to top of BASIC RAM */ +#pragma zpsym("memsize") +extern const struct line* txtptr; /* points to BASIC code */ #pragma zpsym("txtptr") -extern char basbuf[]; /* BASIC's input buffer */ +extern char basbuf[]; /* BASIC's input buffer */ extern void basbuf_len[]; #pragma zpsym("basbuf_len") @@ -75,43 +79,62 @@ extern void basbuf_len[]; int __fastcall__ exec (const char* progname, const char* cmdline) { static int fd; - static unsigned char dv, n = 0; + static unsigned char dv, n; /* Exclude devices that can't load files. */ + /* (Use hand optimization, to make smaller code.) */ dv = getcurrentdevice (); - if (dv < 8 && dv != 1 || dv > 30) { + if (dv < 8 && __AX__ != 1 || __AX__ > 30) { return _mappederrno (9); /* illegal device number */ } utoa (dv, basic.unit, 10); - /* Don't try to run a program that can't be found. */ - fd = open (progname, O_RDONLY); - if (fd < 0) { - return fd; + /* Tape files can be openned only once; skip this test for the Datasette. */ + if (dv != 1) { + /* Don't try to run a program that can't be found. */ + fd = open (progname, O_RDONLY); + if (fd < 0) { + return -1; + } + close (fd); } - close (fd); + n = 0; do { if ((basic.name[n] = progname[n]) == '\0') { break; } - } while (++n < 20); /* truncate long names */ + } while (++n < 20); /* truncate long names */ basic.name[n] = '\"'; +/* This next part isn't needed by machines that put +** BASIC source and variables in different RAM banks. +*/ +#if !defined(__CBM510__) && !defined(__CBM610__) && !defined(__C128__) + /* cc65 program loads might extend beyond the end of the RAM that is allowed + ** for BASIC. Then, the LOAD statement would complain that it is "out of + ** memory". Some pointers that say where to put BASIC program variables + ** must be changed, so that we do not get that error. One pointer is + ** changed here; a BASIC CLR statement changes the others. + */ + vartab = (char*)memsize - 256; +#endif + /* Build the next program's argument list. */ - basbuf[0] = 0x8f; /* REM token */ + basbuf[0] = 0x8F; /* REM token */ basbuf[1] = '\0'; if (cmdline != NULL) { strncat (basbuf, cmdline, (size_t)basbuf_len - 2); } + /* Tell the ROM where to find that BASIC program. */ #if defined(__CBM510__) || defined(__CBM610__) pokewsys ((unsigned)&txtptr, (unsigned)&basic); #else txtptr = &basic; #endif - /* (The return code, in ST, will be destroyed by LOAD. + /* (The return code, in ST [status], will be destroyed by LOAD. ** So, don't bother to set it here.) */ exit (__AX__); diff --git a/libsrc/cbm/execvars.s b/libsrc/cbm/execvars.s index 02eabc12e..68f8a5d64 100644 --- a/libsrc/cbm/execvars.s +++ b/libsrc/cbm/execvars.s @@ -20,9 +20,15 @@ .include "vic20.inc" .endif - .export _txtptr:zp, _basbuf, _basbuf_len:zp +; exec() is written in C. +; Provide the spellings that the C compiler wants to use. -_txtptr := TXTPTR +.ifdef VARTAB +.exportzp _vartab := VARTAB +.exportzp _memsize := MEMSIZE +.endif -_basbuf := BASIC_BUF -_basbuf_len = BASIC_BUF_LEN +.exportzp _txtptr := TXTPTR + +.export _basbuf := BASIC_BUF +.exportzp _basbuf_len = BASIC_BUF_LEN diff --git a/libsrc/cbm/filedes.s b/libsrc/cbm/filedes.s index 384313b94..ddce1be4d 100644 --- a/libsrc/cbm/filedes.s +++ b/libsrc/cbm/filedes.s @@ -5,6 +5,7 @@ ; + .include "cbm.inc" .include "filedes.inc" .code @@ -29,9 +30,14 @@ found: rts ;-------------------------------------------------------------------------- ; Data -.bss -fdtab: .res MAX_FDS -unittab:.res MAX_FDS - +.data +fdtab: .byte LFN_READ + .byte LFN_WRITE + .byte LFN_WRITE + .res MAX_FDS-3 +unittab:.byte CBMDEV_KBD + .byte CBMDEV_SCREEN + .byte CBMDEV_SCREEN + .res MAX_FDS-3 diff --git a/libsrc/cbm/filevars.s b/libsrc/cbm/filevars.s index 316cf2762..db2dec7b3 100644 --- a/libsrc/cbm/filevars.s +++ b/libsrc/cbm/filevars.s @@ -9,7 +9,7 @@ .importzp devnum -.bss +.segment "INITBSS" curunit: .res 1 diff --git a/libsrc/cbm/mcbpointercolor.s b/libsrc/cbm/mcbpointercolor.s new file mode 100644 index 000000000..c9cb6330e --- /dev/null +++ b/libsrc/cbm/mcbpointercolor.s @@ -0,0 +1,10 @@ +; VIC sprite color for the mouse pointer + + .export _mouse_def_pointercolor + + +.segment "INIT" + +_mouse_def_pointercolor: + + .byte $01 ; White diff --git a/libsrc/cbm/mcbpointershape.s b/libsrc/cbm/mcbpointershape.s new file mode 100644 index 000000000..7364201b1 --- /dev/null +++ b/libsrc/cbm/mcbpointershape.s @@ -0,0 +1,30 @@ +; VIC sprite data for the mouse pointer (an arrow) + + .export _mouse_def_pointershape + + +.segment "INIT" + +_mouse_def_pointershape: + + .byte %11111110, %00000000, %00000000 + .byte %11111100, %00000000, %00000000 + .byte %11111000, %00000000, %00000000 + .byte %11111100, %00000000, %00000000 + .byte %11011110, %00000000, %00000000 + .byte %10001111, %00000000, %00000000 + .byte %00000111, %10000000, %00000000 + .byte %00000011, %11000000, %00000000 + .byte %00000001, %11100000, %00000000 + .byte %00000000, %11110000, %00000000 + .byte %00000000, %01111000, %00000000 + .byte %00000000, %00111000, %00000000 + .byte %00000000, %00000000, %00000000 + .byte %00000000, %00000000, %00000000 + .byte %00000000, %00000000, %00000000 + .byte %00000000, %00000000, %00000000 + .byte %00000000, %00000000, %00000000 + .byte %00000000, %00000000, %00000000 + .byte %00000000, %00000000, %00000000 + .byte %00000000, %00000000, %00000000 + .byte %00000000, %00000000, %00000000 diff --git a/libsrc/cbm/read.s b/libsrc/cbm/read.s index aa692a34a..e0fd8d51b 100644 --- a/libsrc/cbm/read.s +++ b/libsrc/cbm/read.s @@ -26,11 +26,8 @@ .proc initstdin - lda #LFN_READ - sta fdtab+STDIN_FILENO lda #STDIN_FILENO + LFN_OFFS ldx #CBMDEV_KBD - stx unittab+STDIN_FILENO ldy #$FF jsr SETLFS jmp OPEN ; Will always succeed @@ -155,5 +152,3 @@ invalidfd: .bss unit: .res 1 - - diff --git a/libsrc/cbm/write.s b/libsrc/cbm/write.s index fdf7cfbc1..e6da59c0f 100644 --- a/libsrc/cbm/write.s +++ b/libsrc/cbm/write.s @@ -24,12 +24,6 @@ .proc initstdout - lda #LFN_WRITE - sta fdtab+STDOUT_FILENO - sta fdtab+STDERR_FILENO - lda #CBMDEV_SCREEN - sta unittab+STDOUT_FILENO - sta unittab+STDERR_FILENO lda #STDOUT_FILENO + LFN_OFFS jsr @L1 lda #STDERR_FILENO + LFN_OFFS @@ -122,7 +116,3 @@ invalidfd: jmp __directerrno ; Sets _errno, clears _oserror, returns -1 .endproc - - - - diff --git a/libsrc/cbm510/mainargs.s b/libsrc/cbm510/mainargs.s index 7eebccbb3..0ec7d0c4c 100644 --- a/libsrc/cbm510/mainargs.s +++ b/libsrc/cbm510/mainargs.s @@ -31,10 +31,9 @@ .macpack generic - MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name +NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special INIT segment, ; which may be reused after the startup code is run. @@ -61,40 +60,42 @@ initmainargs: ldy #FNAM_LEN lda (sysp0),y tay + lda #0 ; The terminating NUL character stx IndReg ; Look for name in correct bank cpy #NAME_LEN + 1 blt L1 - ldy #NAME_LEN - 1 ; limit the length + ldy #NAME_LEN ; Limit the length + bne L1 ; Branch always L0: lda (ptr1),y - sta name,y -L1: dey +L1: sta name,y + dey bpl L0 jsr restore_bank inc __argc ; argc always is equal to at least 1 ; Find a "rem" token. -; + ldx #0 L2: lda BASIC_BUF,x - bze done ; no "rem," no args. + bze done ; No "rem," no args. inx cmp #REM bne L2 ldy #1 * 2 ; Find the next argument. -; + next: lda BASIC_BUF,x bze done ; End of line reached inx cmp #' ' ; Skip leading spaces - beq next ; + beq next ; Found start of next argument. We've incremented the pointer in X already, so ; it points to the second character of the argument. That is useful because we ; will check now for a quoted argument; in which case, we will have to skip that ; first character. -; + found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character @@ -102,7 +103,7 @@ found: cmp #'"' ; Is the argument quoted? setterm:sta term ; Set end-of-argument marker ; Now, store a pointer to the argument into the next slot. -; + txa ; Get low byte add #<BASIC_BUF sta argv,y ; argv[y]= &arg @@ -114,7 +115,7 @@ setterm:sta term ; Set end-of-argument marker inc __argc ; Found another arg ; Search for the end of the argument. -; + argloop:lda BASIC_BUF,x bze done inx @@ -124,7 +125,7 @@ argloop:lda BASIC_BUF,x ; We've found the end of the argument. X points one character behind it, and ; A contains the terminating character. To make the argument a valid C string, ; replace the terminating character by a zero. -; + lda #$00 sta BASIC_BUF-1,x @@ -136,21 +137,20 @@ argloop:lda BASIC_BUF,x blt next ; Parse next one if not ; (The last vector in argv[] already is NULL.) -; + done: lda #<argv ldx #>argv sta __argv stx __argv + 1 rts -; These arrays are zeroed before initmainargs is called. -; char name[16+1]; -; char* argv[MAXARGS+1]={name}; -; -.bss +.segment "INITBSS" + term: .res 1 name: .res NAME_LEN + 1 .data + +; char* argv[MAXARGS+1]={name}; argv: .addr name - .res MAXARGS * 2, $00 + .res MAXARGS * 2 diff --git a/libsrc/cbm510/mcbdefault.s b/libsrc/cbm510/mcbdefault.s index 028fb4ec1..0db753e92 100644 --- a/libsrc/cbm510/mcbdefault.s +++ b/libsrc/cbm510/mcbdefault.s @@ -8,7 +8,10 @@ ; be called from an interrupt handler. ; + .constructor initmcb .export _mouse_def_callbacks + .import _mouse_def_pointershape + .import _mouse_def_pointercolor .import vic:zp .include "mouse-kernel.inc" @@ -19,14 +22,50 @@ ; Sprite definitions. The first value can be changed to adjust the number ; of the sprite used for the mouse. All others depend on that value. MOUSE_SPR = 0 ; Sprite used for the mouse +MOUSE_SPR_MEM = $F400 ; Memory location MOUSE_SPR_MASK = $01 .shl MOUSE_SPR ; Positive mask MOUSE_SPR_NMASK = .lobyte(.not MOUSE_SPR_MASK) ; Negative mask VIC_SPR_X = (VIC_SPR0_X + 2*MOUSE_SPR) ; Sprite X register VIC_SPR_Y = (VIC_SPR0_Y + 2*MOUSE_SPR) ; Sprite Y register +; -------------------------------------------------------------------------- +; Initialize the mouse sprite. + +.segment "INIT" + +initmcb: + +; Copy the mouse sprite data + + ldx #64 - 1 +@L0: lda _mouse_def_pointershape,x + sta MOUSE_SPR_MEM,x + dex + bpl @L0 + +; Set the mouse sprite pointer + + lda #<(MOUSE_SPR_MEM / 64) + sta $F3F8 + MOUSE_SPR + +; Set the mouse sprite color + + ldx IndReg + lda #15 + sta IndReg + + lda _mouse_def_pointercolor + ldy #VIC_SPR0_COLOR + MOUSE_SPR + sta (vic),y + + stx IndReg + rts + ; -------------------------------------------------------------------------- ; Hide the mouse pointer. Always called with interrupts disabled. +.code + hide: ldy #15 sty IndReg diff --git a/libsrc/cbm510/randomize.s b/libsrc/cbm510/randomize.s index d5420165c..75c419ccb 100644 --- a/libsrc/cbm510/randomize.s +++ b/libsrc/cbm510/randomize.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 05.11.2002 +; 2002-11-05, Ullrich von Bassewitz +; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ @@ -10,7 +11,7 @@ .importzp time __randomize: - ldx time ; Use 50/60HZ clock + ldx time+2 ; Use 50/60HZ clock lda time+1 jmp _srand ; Initialize generator diff --git a/libsrc/cbm610/mainargs.s b/libsrc/cbm610/mainargs.s index 9388eac81..02461ac26 100644 --- a/libsrc/cbm610/mainargs.s +++ b/libsrc/cbm610/mainargs.s @@ -31,10 +31,9 @@ .macpack generic - MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name +NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special INIT segment, ; which may be reused after the startup code is run. @@ -45,9 +44,7 @@ initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. -; Because the buffer, that we're copying into, was zeroed out, -; we don't need to add a NUL character. -; + jsr sys_bank ldy #FNAM lda (sysp0),y ; Get file-name pointer from system bank @@ -61,40 +58,42 @@ initmainargs: ldy #FNAM_LEN lda (sysp0),y tay + lda #0 ; The terminating NUL character stx IndReg ; Look for name in correct bank cpy #NAME_LEN + 1 blt L1 - ldy #NAME_LEN - 1 ; limit the length + ldy #NAME_LEN ; Limit the length + bne L1 ; Branch always L0: lda (ptr1),y - sta name,y -L1: dey +L1: sta name,y + dey bpl L0 jsr restore_bank inc __argc ; argc always is equal to at least 1 ; Find a "rem" token. -; + ldx #0 L2: lda BASIC_BUF,x - bze done ; no "rem," no args. + bze done ; No "rem," no args. inx cmp #REM bne L2 ldy #1 * 2 ; Find the next argument. -; + next: lda BASIC_BUF,x bze done ; End of line reached inx cmp #' ' ; Skip leading spaces - beq next ; + beq next ; Found start of next argument. We've incremented the pointer in X already, so ; it points to the second character of the argument. That is useful because we ; will check now for a quoted argument; in which case, we will have to skip that ; first character. -; + found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character @@ -102,7 +101,7 @@ found: cmp #'"' ; Is the argument quoted? setterm:sta term ; Set end-of-argument marker ; Now, store a pointer to the argument into the next slot. -; + txa ; Get low byte add #<BASIC_BUF sta argv,y ; argv[y]= &arg @@ -114,7 +113,7 @@ setterm:sta term ; Set end-of-argument marker inc __argc ; Found another arg ; Search for the end of the argument. -; + argloop:lda BASIC_BUF,x bze done inx @@ -124,33 +123,32 @@ argloop:lda BASIC_BUF,x ; We've found the end of the argument. X points one character behind it, and ; A contains the terminating character. To make the argument a valid C string, ; replace the terminating character by a zero. -; + lda #$00 sta BASIC_BUF-1,x ; Check if the maximum number of command-line arguments is reached. If not, ; parse the next one. -; + lda __argc ; Get low byte of argument count cmp #MAXARGS ; Maximum number of arguments reached? blt next ; Parse next one if not ; (The last vector in argv[] already is NULL.) -; + done: lda #<argv ldx #>argv sta __argv stx __argv + 1 rts -; These arrays are zeroed before initmainargs is called. -; char name[16+1]; -; char* argv[MAXARGS+1]={name}; -; -.bss +.segment "INITBSS" + term: .res 1 name: .res NAME_LEN + 1 .data + +; char* argv[MAXARGS+1]={name}; argv: .addr name - .res MAXARGS * 2, $00 + .res MAXARGS * 2 diff --git a/libsrc/cbm610/randomize.s b/libsrc/cbm610/randomize.s index a936f8a2f..d313baa1b 100644 --- a/libsrc/cbm610/randomize.s +++ b/libsrc/cbm610/randomize.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 05.11.2002 +; 2002-11-05, Ullrich von Bassewitz +; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ @@ -10,7 +11,7 @@ .importzp time __randomize: - ldx time ; Use 50/60HZ clock + ldx time+2 ; Use 50/60HZ clock lda time+1 jmp _srand ; Initialize generator diff --git a/libsrc/common/_afailed.c b/libsrc/common/_afailed.c index 4e56b93f2..7c6df4a2c 100644 --- a/libsrc/common/_afailed.c +++ b/libsrc/common/_afailed.c @@ -1,7 +1,8 @@ /* ** _afailed.c ** -** Ullrich von Bassewitz, 06.06.1998 +** 1998-06-06, Ullrich von Bassewitz +** 2015-03-13, Greg King */ @@ -11,7 +12,7 @@ -void _afailed (char* file, unsigned line) +void __fastcall__ _afailed (char* file, unsigned line) { fprintf (stderr, "ASSERTION FAILED IN %s(%u)\n", file, line); exit (2); diff --git a/libsrc/common/_cwd.s b/libsrc/common/_cwd.s index eeda10f1d..7b4031f52 100644 --- a/libsrc/common/_cwd.s +++ b/libsrc/common/_cwd.s @@ -14,12 +14,12 @@ .import initcwd .include "stdio.inc" - + __cwd_buf_size = FILENAME_MAX cwd_init := initcwd -.bss +.segment "INITBSS" __cwd: .res __cwd_buf_size @@ -29,4 +29,3 @@ __cwd: .res __cwd_buf_size ; checking the other sources. .assert __cwd_buf_size < 256, error, "__cwd_buf_size must not be > 255" - diff --git a/libsrc/common/_directerrno.s b/libsrc/common/_directerrno.s new file mode 100644 index 000000000..794247148 --- /dev/null +++ b/libsrc/common/_directerrno.s @@ -0,0 +1,27 @@ +; +; 2003-08-12, Ullrich von Bassewitz +; 2015-09-24, Greg King +; +; Helper function for several high-level file functions. +; + + .include "errno.inc" + + .macpack cpu + +; ---------------------------------------------------------------------------- +; int __fastcall__ _directerrno (unsigned char code); +; /* Set errno to a specific error code, clear _oserror, and return -1. Used +; ** by the library. +; */ + +__directerrno: + jsr __seterrno ; Set errno (returns with .A = 0) + sta __oserror ; Clear __oserror +.if (.cpu .bitand CPU_ISET_65SC02) + dec a +.else + lda #$FF ; Return -1 +.endif + tax + rts diff --git a/libsrc/common/_mappederrno.s b/libsrc/common/_mappederrno.s new file mode 100644 index 000000000..33f654c29 --- /dev/null +++ b/libsrc/common/_mappederrno.s @@ -0,0 +1,33 @@ +; +; 2003-08-12, Ullrich von Bassewitz +; 2015-09-24, Greg King +; +; Helper function for several high-level file functions. +; + + .include "errno.inc" + + .macpack generic + .macpack cpu + +; ---------------------------------------------------------------------------- +; int __fastcall__ _mappederrno (unsigned char code); +; /* Set _oserror to the given platform-specific error code. If it is a real +; ** error code (not zero), set errno to the corresponding system error code, +; ** and return -1. Otherwise, return zero. +; ** Used by the library. +; */ + +__mappederrno: + sta __oserror ; Store the error code + tax ; Did we have an error? + bze ok ; Branch if no + jsr __osmaperrno ; Map OS error into errno code + jsr __seterrno ; Save in errno (returns with .A = 0) +.if (.cpu .bitand CPU_ISET_65SC02) + dec a +.else + lda #$FF ; Return -1 if error +.endif + tax +ok: rts diff --git a/libsrc/common/_printf.h b/libsrc/common/_printf.h index ffb2443bd..7914fa870 100644 --- a/libsrc/common/_printf.h +++ b/libsrc/common/_printf.h @@ -16,7 +16,7 @@ struct outdesc; /* Type of the function that is called to output data */ -typedef void (*outfunc) (struct outdesc* desc, const char* buf, unsigned count); +typedef void __cdecl__ (* outfunc) (struct outdesc* desc, const char* buf, unsigned count); diff --git a/libsrc/common/bsearch.c b/libsrc/common/bsearch.c index f6d32a5b5..aafd28592 100644 --- a/libsrc/common/bsearch.c +++ b/libsrc/common/bsearch.c @@ -1,7 +1,8 @@ /* ** bsearch.c ** -** Ullrich von Bassewitz, 17.06.1998 +** 1998-06-17, Ullrich von Bassewitz +** 2015-06-21, Greg King */ @@ -11,7 +12,7 @@ void* __fastcall__ bsearch (const void* key, const void* base, size_t n, - size_t size, int (*cmp) (const void*, const void*)) + size_t size, int __fastcall__ (* cmp) (const void*, const void*)) { int current; int result; diff --git a/libsrc/common/errno.s b/libsrc/common/errno.s index 3a1f1b6c8..f448c3c14 100644 --- a/libsrc/common/errno.s +++ b/libsrc/common/errno.s @@ -1,47 +1,14 @@ ; -; Ullrich von Bassewitz, 2003-08-12 +; 2003-08-12, Ullrich von Bassewitz +; 2015-09-24, Greg King ; -; Helper functions for several high level file functions. +; extern int _errno; +; /* Library errors go here. */ ; - .include "errno.inc" -.code - -; ---------------------------------------------------------------------------- -; int __fastcall__ _directerrno (unsigned char code); -; /* Set errno to a specific error code, clear _oserror and return -1. Used -; ** by the library. -; */ - -__directerrno: - jsr __seterrno ; Set errno, returns with A = 0 - sta __oserror ; Clear __oserror - beq fail ; Branch always - -; ---------------------------------------------------------------------------- -; int __fastcall__ _mappederrno (unsigned char code); -; /* Set _oserror to the given platform specific error code. If it is a real -; ** error code (not zero) set errno to the corresponding system error code -; ** and return -1. Otherwise return zero. -; ** Used by the library. -; */ - -__mappederrno: - sta __oserror ; Store the error code - tax ; Did we have an error? - beq ok ; Branch if no - jsr __osmaperrno ; Map os error into errno code - jsr __seterrno ; Save in errno -fail: lda #$FF ; Return -1 - tax -ok: rts - - -; ---------------------------------------------------------------------------- .bss __errno: .word 0 - diff --git a/libsrc/common/interrupt.s b/libsrc/common/interrupt.s index e1d53d6dc..950d3d787 100644 --- a/libsrc/common/interrupt.s +++ b/libsrc/common/interrupt.s @@ -1,5 +1,6 @@ ; -; Oliver Schmidt, 2012-01-18 +; 2012-01-18, Oliver Schmidt +; 2015-08-22, Greg King ; ; void __fastcall__ set_irq (irq_handler f, void *stack_addr, size_t stack_size); ; void reset_irq (void); @@ -7,8 +8,7 @@ .export _set_irq, _reset_irq .interruptor clevel_irq, 1 ; Export as low priority IRQ handler - .import popax - .importzp __ZP_START__ + .import popax, __ZP_START__ .include "zeropage.inc" @@ -31,6 +31,8 @@ zpsave: .res zpsavespace ; --------------------------------------------------------------------------- +.code + .proc _set_irq ; Keep clevel_irq from being called right now @@ -77,7 +79,7 @@ zpsave: .res zpsavespace ; Save our zero page locations @L1: ldx #.sizeof(::zpsave)-1 -@L2: lda __ZP_START__,x +@L2: lda <__ZP_START__,x sta zpsave,x dex bpl @L2 @@ -94,7 +96,7 @@ zpsave: .res zpsavespace ; Copy back our zero page content ldx #.sizeof(::zpsave)-1 @L3: ldy zpsave,x - sty __ZP_START__,x + sty <__ZP_START__,x dex bpl @L3 @@ -103,4 +105,3 @@ zpsave: .res zpsavespace rts .endproc - diff --git a/libsrc/common/longjmp.s b/libsrc/common/longjmp.s index a89f97fa0..e9bac42e6 100644 --- a/libsrc/common/longjmp.s +++ b/libsrc/common/longjmp.s @@ -1,7 +1,8 @@ ; -; Ullrich von Bassewitz, 06.06.1998 +; 1998-06-06, Ullrich von Bassewitz +; 2015-09-11, Greg King ; -; void longjmp (jmp_buf buf, int retval); +; void __fastcall__ longjmp (jmp_buf buf, int retval); ; .export _longjmp @@ -13,8 +14,8 @@ _longjmp: stx ptr2+1 ora ptr2+1 ; Check for 0 bne @L1 - lda #1 ; 0 is illegal according to the standard... - sta ptr2 ; ... and must be replaced by 1 + inc ptr2 ; 0 is illegal, according to the standard ... + ; ... and, must be replaced by 1 @L1: jsr popax ; get buf sta ptr1 stx ptr1+1 @@ -49,4 +50,3 @@ _longjmp: lda ptr2 ldx ptr2+1 rts - diff --git a/libsrc/common/memmove.s b/libsrc/common/memmove.s index 94ad7d102..9c33124f1 100644 --- a/libsrc/common/memmove.s +++ b/libsrc/common/memmove.s @@ -1,7 +1,7 @@ ; -; Ullrich von Bassewitz, 2003-08-20 -; Performance increase (about 20%) by -; Christian Krueger, 2009-09-13 +; 2003-08-20, Ullrich von Bassewitz +; 2009-09-13, Christian Krueger -- performance increase (about 20%) +; 2015-10-23, Greg King ; ; void* __fastcall__ memmove (void* dest, const void* src, size_t size); ; @@ -23,8 +23,7 @@ _memmove: ; low addresses and increase pointers), otherwise we must copy downwards ; (start at high addresses and decrease pointers). - sec - sbc ptr1 + cmp ptr1 txa sbc ptr1+1 jcc memcpy_upwards ; Branch if dest < src (upwards copy) @@ -81,4 +80,3 @@ PageSizeCopy: ; assert Y = 0 ; Done, return dest done: jmp popax ; Pop ptr and return as result - diff --git a/libsrc/common/moveinit.s b/libsrc/common/moveinit.s new file mode 100644 index 000000000..2b22be02d --- /dev/null +++ b/libsrc/common/moveinit.s @@ -0,0 +1,45 @@ +; +; 2015-10-07, Greg King +; + + .export moveinit + + .import __INIT_LOAD__, __INIT_RUN__, __INIT_SIZE__ ; Linker-generated + + .macpack cpu + .macpack generic + + +; Put this in the DATA segment because it is self-modifying code. + +.data + +; Move the INIT segment from where it was loaded (over the bss segments) +; into where it must be run (over the BSS segment). The two areas might overlap; +; and, the segment is moved upwards. Therefore, this code starts at the highest +; address, and decrements to the lowest address. The low bytes of the starting +; pointers are not sums. The high bytes are sums; but, they do not include the +; carry. Both the low-byte sums and the carries will be done when the pointers +; are indexed by the .Y register. + +moveinit: + +; First, move the last, partial page. +; Then, move all of the full pages. + + ldy #<__INIT_SIZE__ ; size of partial page + ldx #>__INIT_SIZE__ + (<__INIT_SIZE__ <> 0) ; number of pages, including partial + +L1: dey +init_load: + lda __INIT_LOAD__ + (__INIT_SIZE__ & $FF00) - $0100 * (<__INIT_SIZE__ = 0),y +init_run: + sta __INIT_RUN__ + (__INIT_SIZE__ & $FF00) - $0100 * (<__INIT_SIZE__ = 0),y + tya + bnz L1 ; page not finished + + dec init_load+2 + dec init_run+2 + dex + bnz L1 ; move next page + rts diff --git a/libsrc/common/qsort.c b/libsrc/common/qsort.c index df02095ed..991db3ba1 100644 --- a/libsrc/common/qsort.c +++ b/libsrc/common/qsort.c @@ -1,7 +1,8 @@ /* ** qsort.c ** -** Ullrich von Bassewitz, 09.12.1998 +** 1998.12.09, Ullrich von Bassewitz +** 2015-06-21, Greg King */ @@ -12,7 +13,7 @@ static void QuickSort (register unsigned char* Base, int Lo, int Hi, register size_t Size, - int (*Compare)(const void*, const void*)) + int __fastcall__ (* Compare) (const void*, const void*)) /* Internal recursive function. Works with ints, but this shouldn't be ** a problem. */ @@ -52,7 +53,7 @@ static void QuickSort (register unsigned char* Base, int Lo, int Hi, void __fastcall__ qsort (void* base, size_t nmemb, size_t size, - int (*compare)(const void*, const void*)) + int __fastcall__ (* compare) (const void*, const void*)) /* Quicksort implementation */ { if (nmemb > 1) { diff --git a/libsrc/common/setjmp.s b/libsrc/common/setjmp.s index a6448b29f..a763ac3ec 100644 --- a/libsrc/common/setjmp.s +++ b/libsrc/common/setjmp.s @@ -1,10 +1,13 @@ ; -; Ullrich von Bassewitz, 06.06.1998 +; 1998-06-06, Ullrich von Bassewitz +; 2015-09-11, Greg King ; -; int setjmp (jmp_buf buf); +; int __fastcall__ setjmp (jmp_buf buf); ; .export __setjmp + + .import return0 .importzp sp, ptr1 __setjmp: @@ -44,9 +47,4 @@ __setjmp: ; Return zero - lda #0 - tax - rts - - - + jmp return0 diff --git a/libsrc/common/vfprintf.s b/libsrc/common/vfprintf.s index 9812f661b..1225bcc47 100644 --- a/libsrc/common/vfprintf.s +++ b/libsrc/common/vfprintf.s @@ -33,7 +33,7 @@ ptr: .res 2 ; Points to output file ; can ignore the passed pointer d, and access the data directly. While this ; is not very clean, it gives better and shorter code. ; -; static void out (struct outdesc* d, const char* buf, unsigned count) +; static void cdecl out (struct outdesc* d, const char* buf, unsigned count) ; /* Routine used for writing */ ; { ; register size_t cnt; @@ -56,7 +56,7 @@ out: ldy #5 ldy #7 jsr pushwysp ; Push count lda ptr - ldx ptr+1 + ldx ptr+1 jsr _fwrite sta ptr1 ; Save function result stx ptr1+1 diff --git a/libsrc/common/vsnprintf.s b/libsrc/common/vsnprintf.s index db82bdaf3..228e531d0 100644 --- a/libsrc/common/vsnprintf.s +++ b/libsrc/common/vsnprintf.s @@ -1,7 +1,8 @@ ; -; int vsnprintf (char* Buf, size_t size, const char* Format, va_list ap); +; int __fastcall__ vsnprintf (char* Buf, size_t size, const char* Format, va_list ap); ; -; Ullrich von Bassewitz, 2009-09-26 +; 2009-09-26, Ullrich von Bassewitz +; 2015-07-17, Greg King ; .export _vsnprintf, vsnprintf @@ -9,6 +10,8 @@ .import _memcpy, __printf .importzp sp, ptr1 + .include "errno.inc" + .macpack generic .data @@ -46,8 +49,10 @@ vsnprintf: sta ccount+1 ; Clear ccount ; Get the size parameter and replace it by a pointer to outdesc. This is to -; build a stack frame for the call to _printf. -; If size is zero, there's nothing to do. +; build a stack frame for the call to _printf. The size must not be greater +; than INT_MAX because the return type is int. If the size is zero, +; then nothing will be written into the buffer; but, the arguments still will +; be formatted and counted. ldy #2 lda (sp),y @@ -58,15 +63,13 @@ vsnprintf: iny lda (sp),y + bmi L9 ; More than $7FFF sta ptr1+1 - ora ptr1 - beq L9 - lda #>outdesc sta (sp),y -; Write size-1 to outdesc.uns +; Write size-1 to outdesc.uns. It will be -1 if there is no buffer. ldy ptr1+1 ldx ptr1 @@ -83,24 +86,32 @@ L1: dex sta bufptr+0 stx bufptr+1 +; There must be a buffer if its size is non-zero. + + bit bufsize+1 + bmi L5 + ora bufptr+1 + bze L0 ; The pointer shouldn't be NULL + ; Restore ap and call _printf - pla +L5: pla tax pla jsr __printf -; Terminate the string. The last char is either at bufptr+ccount or -; bufptr+bufsize, whichever is smaller. +; Terminate the string if there is a buffer. The last char. is at either +; bufptr+bufsize or bufptr+ccount, whichever is smaller. + ldx bufsize+1 + bmi L4 ; -1 -- No buffer + lda bufsize+0 + cpx ccount+1 + bne L2 + cmp ccount+0 +L2: bcc L3 lda ccount+0 ldx ccount+1 - cpx bufsize+1 - bne L2 - cmp bufsize+0 -L2: bcc L3 - lda bufsize+0 - ldx bufsize+1 clc L3: adc bufptr+0 sta ptr1 @@ -114,23 +125,29 @@ L3: adc bufptr+0 ; Return the number of bytes written and drop buf - lda ccount+0 +L4: lda ccount+0 ldx ccount+1 jmp incsp2 -; Bail out if size is zero. +; Bail out if size is too high. -L9: pla - pla ; Discard ap - lda #0 - tax +L9: ldy #ERANGE + .byte $2C ;(bit $xxxx) + +; NULL buffer pointers usually are invalid. + +L0: ldy #EINVAL + pla ; Drop ap + pla + tya + jsr __directerrno ; Return -1 jmp incsp6 ; Drop parameters ; ---------------------------------------------------------------------------- ; Callback routine used for the actual output. ; -; static void out (struct outdesc* d, const char* buf, unsigned count) +; static void __cdecl__ out (struct outdesc* d, const char* buf, unsigned count) ; /* Routine used for writing */ ; ; Since we know, we're called with a pointer to our static outdesc structure, @@ -146,10 +163,11 @@ out: sbc ccount+0 ; Low byte of bytes already written sta ptr1 lda bufsize+1 + bmi @L9 ; -1 -- No buffer sbc ccount+1 sta ptr1+1 bcs @L0 ; Branch if space left - lda #$00 +@L9: lda #$0000 sta ptr1 sta ptr1+1 ; No space left diff --git a/libsrc/common/zerobss.s b/libsrc/common/zerobss.s index de160aeef..2c500f773 100644 --- a/libsrc/common/zerobss.s +++ b/libsrc/common/zerobss.s @@ -9,7 +9,7 @@ .importzp ptr1 -.segment "INIT" +.code zerobss: lda #<__BSS_RUN__ @@ -41,6 +41,3 @@ L3: cpy #<__BSS_SIZE__ ; Done L4: rts - - - diff --git a/libsrc/conio/vcprintf.s b/libsrc/conio/vcprintf.s index 5dbbc051d..06eab4421 100644 --- a/libsrc/conio/vcprintf.s +++ b/libsrc/conio/vcprintf.s @@ -1,5 +1,5 @@ ; -; int vcprintf (const char* Format, va_list ap); +; int __fastcall__ vcprintf (const char* Format, va_list ap); ; ; Ullrich von Bassewitz, 2.12.2000 ; @@ -30,7 +30,7 @@ outdesc: ; Static outdesc structure ; ---------------------------------------------------------------------------- ; Callback routine used for the actual output. ; -; static void out (struct outdesc* d, const char* buf, unsigned count) +; static void __cdecl__ out (struct outdesc* d, const char* buf, unsigned count) ; /* Routine used for writing */ ; { ; /* Fast screen output */ @@ -94,7 +94,7 @@ out: jsr popax ; count ; ---------------------------------------------------------------------------- ; vcprintf - formatted console i/o ; -; int vcprintf (const char* format, va_list ap) +; int __fastcall__ vcprintf (const char* format, va_list ap) ; { ; struct outdesc d; ; @@ -107,10 +107,6 @@ out: jsr popax ; count ; /* Return bytes written */ ; return d.ccount; ; } -; -; It is intentional that this function does not have __fastcall__ calling -; conventions - we need the space on the stack anyway, so there's nothing -; gained by using __fastcall__. _vcprintf: sta ptr1 ; Save ap @@ -153,6 +149,3 @@ _vcprintf: lda outdesc ; ccount ldx outdesc+1 rts - - - diff --git a/libsrc/conio/vcscanf.s b/libsrc/conio/vcscanf.s index 67d5f664f..6893da4ef 100644 --- a/libsrc/conio/vcscanf.s +++ b/libsrc/conio/vcscanf.s @@ -63,7 +63,7 @@ L1: jsr _cgetc ; ---------------------------------------------------------------------------- -; static int unget(int c) { +; static int cdecl unget(int c) { ; pushed = true; ; return back = c; ; } @@ -127,4 +127,3 @@ d: .addr get ; SCANFDATA::GET pla jmp __scanf .endproc - diff --git a/libsrc/dbg/dbgdump.s b/libsrc/dbg/dbgdump.s index b2045872f..8ab646d21 100644 --- a/libsrc/dbg/dbgdump.s +++ b/libsrc/dbg/dbgdump.s @@ -1,7 +1,7 @@ ; ; Ullrich von Bassewitz, 11.08.1998 ; -; char* DbgMemDump (unsigend Addr, char* Buf, unsigned char Length); +; char* __cdecl__ DbgMemDump (unsigend Addr, char* Buf, unsigned char Length); ; .export _DbgMemDump diff --git a/libsrc/joystick/joy-kernel.s b/libsrc/joystick/joy-kernel.s index 1ba3056d8..2b1dcf884 100644 --- a/libsrc/joystick/joy-kernel.s +++ b/libsrc/joystick/joy-kernel.s @@ -109,7 +109,7 @@ inv_drv: copy: lda (ptr1),y iny -set: sta joy_vectors,x + sta joy_vectors,x inx rts diff --git a/libsrc/nes/irq.s b/libsrc/nes/irq.s new file mode 100644 index 000000000..9c026f0ed --- /dev/null +++ b/libsrc/nes/irq.s @@ -0,0 +1,19 @@ +; +; IRQ handling (NES version) +; + + .export initirq, doneirq + +; ------------------------------------------------------------------------ + +.segment "INIT" + +initirq: + rts + +; ------------------------------------------------------------------------ + +.code + +doneirq: + rts diff --git a/libsrc/nes/joy/nes-stdjoy.s b/libsrc/nes/joy/nes-stdjoy.s index b50c2124d..b5e653c16 100644 --- a/libsrc/nes/joy/nes-stdjoy.s +++ b/libsrc/nes/joy/nes-stdjoy.s @@ -95,9 +95,9 @@ READJOY: tay ; Joystick number (0,1) into Y lda #1 - sta APU_PAD1,y + sta APU_PAD1 lda #0 - sta APU_PAD1,y + sta APU_PAD1 ; Read joystick diff --git a/libsrc/osic1p/bootstrap.s b/libsrc/osic1p/bootstrap.s new file mode 100644 index 000000000..2a501b980 --- /dev/null +++ b/libsrc/osic1p/bootstrap.s @@ -0,0 +1,153 @@ +; +; 2015-03-08, Greg King +; + +; When you want to create a program with the alternate file format, +; add "-u __BOOT__" to the cl65/ld65 command line. Then, the linker +; will import this symbol name; and, link this module at the front +; of your program file. +; + .export __BOOT__:abs = 1 + + .import __RAM_START__, __RAM_SIZE__, __BSS_RUN__ + +; ------------------------------------------------------------------------ + +load_addr := __RAM_START__ +load_size = __BSS_RUN__ - __RAM_START__ +ram_top := __RAM_START__ + __RAM_SIZE__ + + .segment "BOOT" + +; If you want to change how this bootstrap loader works, then: +; 1. edit this assembly source code, +; 2. define the constant ASM (uncomment the line below), +; 3. assemble this file (and, make a listing of that assembly), +; 4. copy the listing's hex codes into the .byte lines below (notice that most +; of the strings are followed by CR; it's required by the OS65V monitor) +; (be sure to match the listing's lines against the .byte lines), +; 5. undefine ASM (recomment the line), +; 6. assemble this file, again, +; 7. and, add the object file to "osic1p.lib". + +;ASM = 1 + +.ifdef ASM + + .include "osic1p.inc" + .macpack generic + +load := $08 ; private variables +count := $0A + +GETCHAR := $FFBF ; gets one character from ACIA + +FIRSTVISC = $85 ; Offset of first visible character in video RAM +LINEDIST = $20 ; Offset in video RAM between two lines + + ldy #<$0000 + lda #<load_addr + ldx #>load_addr + sta load + stx load+1 + lda #<load_size + eor #$FF + sta count ; store (-size - 1) + lda #>load_size + eor #$FF + sta count+1 + +L1: inc count ; pre-count one's-complement upwards + bnz L2 + inc count+1 + bze L3 +L2: jsr GETCHAR ; (doesn't change .Y) + sta (load),y + +; Show that the file is being loaded by rotating an arrow on the screen. +; + tya + lsr a + lsr a + and #8 - 1 + ora #$10 ; eight arrow characters + sta SCRNBASE + FIRSTVISC + 2 * LINEDIST + 11 + + iny + bnz L1 + inc load+1 + bnz L1 ; branch always + +L3: jmp load_addr + +.else + +.mac hex1 h + .lobytes ((h) & $0F) + (((h) & $0F) > 9) * 7 + '0' +.endmac + +.mac hex2 h + hex1 (h) >> 4 + hex1 (h) >> 0 +.endmac + +.mac hex4 h + hex2 >(h) + hex2 <(h) +.endmac + +CR = $0D + + .byte CR, CR + .byte "." ; set an address + hex4 ram_top ; put loader where stack will sit + .byte "/" ; write bytes into RAM + +; ASCII-coded hexadecimal translation of the above assembly code. +; It was copied from the assembler listing. + + .byte "A0", CR, "00", CR + .byte "A9", CR + hex2 <load_addr + .byte CR, "A2", CR + hex2 >load_addr + .byte CR, "85", CR, "08", CR + .byte "86", CR, "09", CR + .byte "A9", CR + hex2 <load_size + .byte CR, "49", CR, "FF", CR + .byte "85", CR, "0A", CR + .byte "A9", CR + hex2 >load_size + .byte CR, "49", CR, "FF", CR + .byte "85", CR, "0B", CR + + .byte "E6", CR, "0A", CR + .byte "D0", CR, "04", CR + .byte "E6", CR, "0B", CR + .byte "F0", CR, "16", CR + .byte "20", CR, "BF", CR, "FF", CR + .byte "91", CR, "08", CR + + .byte "98", CR + .byte "4A", CR + .byte "4A", CR + .byte "29", CR, "07", CR + .byte "09", CR, "10", CR + .byte "8D", CR, "D0", CR, "D0", CR + + .byte "C8", CR + .byte "D0", CR, "E6", CR + .byte "E6", CR, "09", CR + .byte "D0", CR, "E2", CR + + .byte "4C", CR + hex2 <load_addr + .byte CR + hex2 >load_addr + + .byte CR, "." + hex4 ram_top + .byte "G" ; go to address + +.endif diff --git a/libsrc/osic1p/cclear.s b/libsrc/osic1p/cclear.s new file mode 100644 index 000000000..2036c38e0 --- /dev/null +++ b/libsrc/osic1p/cclear.s @@ -0,0 +1,29 @@ +; +; Copied from CBM implementation +; +; originally by: +; Ullrich von Bassewitz, 08.08.1998 +; +; void cclearxy (unsigned char x, unsigned char y, unsigned char length); +; void cclear (unsigned char length); +; + + .export _cclearxy, _cclear + .import popa, _gotoxy, cputdirect + .importzp tmp1 + +_cclearxy: + pha ; Save the length + jsr popa ; Get y + jsr _gotoxy ; Call this one, will pop params + pla ; Restore the length and run into _cclear + +_cclear: + cmp #0 ; Is the length zero? + beq L9 ; Jump if done + sta tmp1 +L1: lda #' ' + jsr cputdirect ; Direct output + dec tmp1 + bne L1 +L9: rts diff --git a/libsrc/osic1p/cgetc.s b/libsrc/osic1p/cgetc.s new file mode 100644 index 000000000..5ddca2870 --- /dev/null +++ b/libsrc/osic1p/cgetc.s @@ -0,0 +1,50 @@ +; +; 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 "INIT" +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 diff --git a/libsrc/osic1p/chline.s b/libsrc/osic1p/chline.s new file mode 100644 index 000000000..be40d40af --- /dev/null +++ b/libsrc/osic1p/chline.s @@ -0,0 +1,29 @@ +; +; based on CBM implementation +; +; originally by: +; Ullrich von Bassewitz, 08.08.1998 +; +; void chlinexy (unsigned char x, unsigned char y, unsigned char length); +; void chline (unsigned char length); +; + + .export _chlinexy, _chline + .import popa, _gotoxy, cputdirect + .importzp tmp1 + +_chlinexy: + pha ; Save the length + jsr popa ; Get y + jsr _gotoxy ; Call this one, will pop params + pla ; Restore the length + +_chline: + cmp #0 ; Is the length zero? + beq L9 ; Jump if done + sta tmp1 +L1: lda #$94 ; Horizontal line, screen code + jsr cputdirect ; Direct output + dec tmp1 + bne L1 +L9: rts diff --git a/libsrc/osic1p/crt0.s b/libsrc/osic1p/crt0.s new file mode 100644 index 000000000..62342c206 --- /dev/null +++ b/libsrc/osic1p/crt0.s @@ -0,0 +1,55 @@ +; --------------------------------------------------------------------------- +; crt0.s +; --------------------------------------------------------------------------- +; +; Startup code for Ohio Scientific Challenger 1P + +.export _init, _exit +.import _main + +.export __STARTUP__ : absolute = 1 ; Mark as startup +.import __RAM_START__, __RAM_SIZE__ ; Linker generated +.import __STACKSIZE__ + +.import zerobss, initlib, donelib + +.include "zeropage.inc" +.include "extzp.inc" +.include "osic1p.inc" + +; --------------------------------------------------------------------------- +; Place the startup code in a special segment + +.segment "STARTUP" + +; --------------------------------------------------------------------------- +; A little light 6502 housekeeping + +_init: ldx #$FF ; Initialize stack pointer to $01FF + txs + cld ; Clear decimal mode + +; --------------------------------------------------------------------------- +; Set cc65 argument stack pointer + + lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) + sta sp + lda #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) + sta sp+1 + +; --------------------------------------------------------------------------- +; Initialize memory storage + + jsr zerobss ; Clear BSS segment + jsr initlib ; Run constructors + +; --------------------------------------------------------------------------- +; Call main() + + jsr _main + +; --------------------------------------------------------------------------- +; Back from main (this is also the _exit entry): + +_exit: jsr donelib ; Run destructors + jmp RESET ; Display boot menu after program exit diff --git a/libsrc/osic1p/ctype.s b/libsrc/osic1p/ctype.s new file mode 100644 index 000000000..fa901c189 --- /dev/null +++ b/libsrc/osic1p/ctype.s @@ -0,0 +1,289 @@ +; +; Character specification table. +; +; Ullrich von Bassewitz, 02.06.1998 +; 2003-05-02, Greg King +; +; Copied from cbm/ctype.s + +; The following 256-byte-wide table specifies attributes for the isxxx type +; of functions. Doing it by a table means some overhead in space, but it +; has major advantages: +; +; * It is fast. If it weren't for the slow parameter-passing of cc65, +; one even could define C-language macroes for the isxxx functions +; (as it usually is done, on other platforms). +; +; * It is highly portable. The only unportable part is the table itself; +; all real code goes into the common library. +; +; * We save some code in the isxxx functions. + +; This table is taken from Craig S. Bruce's technical docs. for the ACE OS. + + .include "ctype.inc" + +; The table is read-only, put it into the RODATA segment. + + .rodata + +__ctype: + .byte CT_CTRL ; 0/00 ___rvs_@___ + .byte CT_CTRL ; 1/01 ___rvs_a___ + .byte CT_CTRL ; 2/02 ___rvs_b___ + .byte CT_CTRL ; 3/03 ___rvs_c___ + .byte CT_CTRL ; 4/04 ___rvs_d___ + .byte CT_CTRL ; 5/05 ___rvs_e___ + .byte CT_CTRL ; 6/06 ___rvs_f___ + .byte CT_CTRL ; 7/07 _BEL/rvs_g_ + .byte CT_CTRL ; 8/08 ___rvs_h___ + .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 _TAB/rvs_i_ + .byte CT_CTRL | CT_OTHER_WS ; 10/0a _BOL/rvs_j_ + .byte CT_CTRL ; 11/0b ___rvs_k___ + .byte CT_CTRL ; 12/0c ___rvs_l___ + .byte CT_CTRL | CT_OTHER_WS ; 13/0d _CR_/rvs_m_ + .byte CT_CTRL ; 14/0e ___rvs_n___ + .byte CT_CTRL ; 15/0f ___rvs_o___ + .byte CT_CTRL ; 16/10 ___rvs_p___ + .byte CT_CTRL | CT_OTHER_WS ; 17/11 _VT_/rvs_q_ + .byte CT_CTRL ; 18/12 ___rvs_r___ + .byte CT_CTRL | CT_OTHER_WS ; 19/13 HOME/rvs_s_ + .byte CT_CTRL | CT_OTHER_WS ; 20/14 _BS_/rvs_t_ + .byte CT_CTRL ; 21/15 ___rvs_u___ + .byte CT_CTRL ; 22/16 ___rvs_v___ + .byte CT_CTRL ; 23/17 ___rvs_w___ + .byte CT_CTRL ; 24/18 ___rvs_x___ + .byte CT_CTRL ; 25/19 ___rvs_y___ + .byte CT_CTRL ; 26/1a ___rvs_z___ + .byte CT_CTRL ; 27/1b ___rvs_[___ + .byte CT_CTRL ; 28/1c ___rvs_\___ + .byte CT_CTRL | CT_OTHER_WS ; 29/1d cursr-right + .byte CT_CTRL ; 30/1e ___rvs_^___ + .byte CT_CTRL ; 31/1f _rvs_under_ + .byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___ + .byte $00 ; 33/21 _____!_____ + .byte $00 ; 34/22 _____"_____ + .byte $00 ; 35/23 _____#_____ + .byte $00 ; 36/24 _____$_____ + .byte $00 ; 37/25 _____%_____ + .byte $00 ; 38/26 _____&_____ + .byte $00 ; 39/27 _____'_____ + .byte $00 ; 40/28 _____(_____ + .byte $00 ; 41/29 _____)_____ + .byte $00 ; 42/2a _____*_____ + .byte $00 ; 43/2b _____+_____ + .byte $00 ; 44/2c _____,_____ + .byte $00 ; 45/2d _____-_____ + .byte $00 ; 46/2e _____._____ + .byte $00 ; 47/2f _____/_____ + .byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____ + .byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____ + .byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____ + .byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____ + .byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____ + .byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____ + .byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____ + .byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____ + .byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____ + .byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____ + .byte $00 ; 58/3a _____:_____ + .byte $00 ; 59/3b _____;_____ + .byte $00 ; 60/3c _____<_____ + .byte $00 ; 61/3d _____=_____ + .byte $00 ; 62/3e _____>_____ + .byte $00 ; 63/3f _____?_____ + + .byte $00 ; 64/40 _____@_____ + .byte CT_LOWER | CT_XDIGIT ; 65/41 _____a_____ + .byte CT_LOWER | CT_XDIGIT ; 66/42 _____b_____ + .byte CT_LOWER | CT_XDIGIT ; 67/43 _____c_____ + .byte CT_LOWER | CT_XDIGIT ; 68/44 _____d_____ + .byte CT_LOWER | CT_XDIGIT ; 69/45 _____e_____ + .byte CT_LOWER | CT_XDIGIT ; 70/46 _____f_____ + .byte CT_LOWER ; 71/47 _____g_____ + .byte CT_LOWER ; 72/48 _____h_____ + .byte CT_LOWER ; 73/49 _____i_____ + .byte CT_LOWER ; 74/4a _____j_____ + .byte CT_LOWER ; 75/4b _____k_____ + .byte CT_LOWER ; 76/4c _____l_____ + .byte CT_LOWER ; 77/4d _____m_____ + .byte CT_LOWER ; 78/4e _____n_____ + .byte CT_LOWER ; 79/4f _____o_____ + .byte CT_LOWER ; 80/50 _____p_____ + .byte CT_LOWER ; 81/51 _____q_____ + .byte CT_LOWER ; 82/52 _____r_____ + .byte CT_LOWER ; 83/53 _____s_____ + .byte CT_LOWER ; 84/54 _____t_____ + .byte CT_LOWER ; 85/55 _____u_____ + .byte CT_LOWER ; 86/56 _____v_____ + .byte CT_LOWER ; 87/57 _____w_____ + .byte CT_LOWER ; 88/58 _____x_____ + .byte CT_LOWER ; 89/59 _____y_____ + .byte CT_LOWER ; 90/5a _____z_____ + .byte $00 ; 91/5b _____[_____ + .byte $00 ; 92/5c _____\_____ + .byte $00 ; 93/5d _____]_____ + .byte $00 ; 94/5e _____^_____ + .byte $00 ; 95/5f _UNDERLINE_ + .byte $00 ; 96/60 _A`_grave__ + .byte $00 ; 97/61 _A'_acute__ + .byte $00 ; 98/62 _A^_circum_ + .byte $00 ; 99/63 _A~_tilde__ + .byte $00 ; 100/64 _A"_dieres_ + .byte $00 ; 101/65 _A__ring___ + .byte $00 ; 102/66 _AE________ + .byte $00 ; 103/67 _C,cedilla_ + .byte $00 ; 104/68 _E`_grave__ + .byte $00 ; 105/69 _E'_acute__ + .byte $00 ; 106/6a _E^_circum_ + .byte $00 ; 107/6b _E"_dieres_ + .byte $00 ; 108/6c _I`_grave__ + .byte $00 ; 109/6d _I'_acute__ + .byte $00 ; 110/6e _I^_circum_ + .byte $00 ; 111/6f _I"_dieres_ + .byte $00 ; 112/70 _D-_Eth_lr_ + .byte $00 ; 113/71 _N~_tilde__ + .byte $00 ; 114/72 _O`_grave__ + .byte $00 ; 115/73 _O'_acute__ + .byte $00 ; 116/74 _O^_circum_ + .byte $00 ; 117/75 _O~_tilde__ + .byte $00 ; 118/76 _O"_dieres_ + .byte $00 ; 119/77 __multiply_ + .byte $00 ; 120/78 _O/_slash__ + .byte $00 ; 121/79 _U`_grave__ + .byte $00 ; 122/7a _U'_acute__ + .byte $00 ; 123/7b _U^_circum_ + .byte $00 ; 124/7c _U"_dieres_ + .byte $00 ; 125/7d _Y'_acute__ + .byte $00 ; 126/7e _cap_thorn_ + .byte $00 ; 127/7f _Es-sed_B__ + + .byte CT_CTRL ; 128/80 __bullet___ + .byte CT_CTRL ; 129/81 __v_line___ + .byte CT_CTRL ; 130/82 __h_line___ + .byte CT_CTRL ; 131/83 ___cross___ + .byte CT_CTRL ; 132/84 _tl_corner_ + .byte CT_CTRL ; 133/85 _tr_corner_ + .byte CT_CTRL ; 134/86 _bl_corner_ + .byte CT_CTRL ; 135/87 _br_corner_ + .byte CT_CTRL ; 136/88 ___l_tee___ + .byte CT_CTRL ; 137/89 ___r_tee___ + .byte CT_CTRL ; 138/8a ___t_tee___ + .byte CT_CTRL ; 139/8b ___b_tee___ + .byte CT_CTRL ; 140/8c ___heart___ + .byte CT_CTRL | CT_OTHER_WS ; 141/8d _CR/diamond + .byte CT_CTRL ; 142/8e ___club____ + .byte CT_CTRL ; 143/8f ___spade___ + .byte CT_CTRL ; 144/90 _s_circle__ + .byte CT_CTRL | CT_OTHER_WS ; 145/91 _cursor-up_ + .byte CT_CTRL ; 146/92 ___pound___ + .byte CT_CTRL | CT_OTHER_WS ; 147/93 _CLS/check_ + .byte CT_CTRL | CT_OTHER_WS ; 148/94 __INSert___ + .byte CT_CTRL ; 149/95 ____+/-____ + .byte CT_CTRL ; 150/96 __divide___ + .byte CT_CTRL ; 151/97 __degree___ + .byte CT_CTRL ; 152/98 _c_checker_ + .byte CT_CTRL ; 153/99 _f_checker_ + .byte CT_CTRL ; 154/9a _solid_sq__ + .byte CT_CTRL ; 155/9b __cr_char__ + .byte CT_CTRL ; 156/9c _up_arrow__ + .byte CT_CTRL | CT_OTHER_WS ; 157/9d cursor-left + .byte CT_CTRL ; 158/9e _left_arro_ + .byte CT_CTRL ; 159/9f _right_arr_ + .byte CT_SPACE | CT_SPACE_TAB ; 160/a0 _req space_ + .byte $00 ; 161/a1 _!_invertd_ + .byte $00 ; 162/a2 ___cent____ + .byte $00 ; 163/a3 ___pound___ + .byte $00 ; 164/a4 __currency_ + .byte $00 ; 165/a5 ____yen____ + .byte $00 ; 166/a6 _|_broken__ + .byte $00 ; 167/a7 __section__ + .byte $00 ; 168/a8 __umulaut__ + .byte $00 ; 169/a9 _copyright_ + .byte $00 ; 170/aa __fem_ord__ + .byte $00 ; 171/ab _l_ang_quo_ + .byte $00 ; 172/ac ____not____ + .byte $00 ; 173/ad _syl_hyphn_ + .byte $00 ; 174/ae _registerd_ + .byte $00 ; 175/af _overline__ + .byte $00 ; 176/b0 __degrees__ + .byte $00 ; 177/b1 ____+/-____ + .byte $00 ; 178/b2 _2_supersc_ + .byte $00 ; 179/b3 _3_supersc_ + .byte $00 ; 180/b4 ___acute___ + .byte $00 ; 181/b5 ____mu_____ + .byte $00 ; 182/b6 _paragraph_ + .byte $00 ; 183/b7 __mid_dot__ + .byte $00 ; 184/b8 __cedilla__ + .byte $00 ; 185/b9 _1_supersc_ + .byte $00 ; 186/ba __mas_ord__ + .byte $00 ; 187/bb _r_ang_quo_ + .byte $00 ; 188/bc ____1/4____ + .byte $00 ; 189/bd ____1/2____ + .byte $00 ; 190/be ____3/4____ + .byte $00 ; 191/bf _?_invertd_ + + .byte $00 ; 192/c0 _____`_____ + .byte CT_UPPER | CT_XDIGIT ; 193/c1 _____A_____ + .byte CT_UPPER | CT_XDIGIT ; 194/c2 _____B_____ + .byte CT_UPPER | CT_XDIGIT ; 195/c3 _____C_____ + .byte CT_UPPER | CT_XDIGIT ; 196/c4 _____D_____ + .byte CT_UPPER | CT_XDIGIT ; 197/c5 _____E_____ + .byte CT_UPPER | CT_XDIGIT ; 198/c6 _____F_____ + .byte CT_UPPER ; 199/c7 _____G_____ + .byte CT_UPPER ; 200/c8 _____H_____ + .byte CT_UPPER ; 201/c9 _____I_____ + .byte CT_UPPER ; 202/ca _____J_____ + .byte CT_UPPER ; 203/cb _____K_____ + .byte CT_UPPER ; 204/cc _____L_____ + .byte CT_UPPER ; 205/cd _____M_____ + .byte CT_UPPER ; 206/ce _____N_____ + .byte CT_UPPER ; 207/cf _____O_____ + .byte CT_UPPER ; 208/d0 _____P_____ + .byte CT_UPPER ; 209/d1 _____Q_____ + .byte CT_UPPER ; 210/d2 _____R_____ + .byte CT_UPPER ; 211/d3 _____S_____ + .byte CT_UPPER ; 212/d4 _____T_____ + .byte CT_UPPER ; 213/d5 _____U_____ + .byte CT_UPPER ; 214/d6 _____V_____ + .byte CT_UPPER ; 215/d7 _____W_____ + .byte CT_UPPER ; 216/d8 _____X_____ + .byte CT_UPPER ; 217/d9 _____Y_____ + .byte CT_UPPER ; 218/da _____Z_____ + .byte $00 ; 219/db _____{_____ + .byte $00 ; 220/dc _____|_____ + .byte $00 ; 221/dd _____}_____ + .byte $00 ; 222/de _____~_____ + .byte $00 ; 223/df ___HOUSE___ + .byte $00 ; 224/e0 _a`_grave__ + .byte $00 ; 225/e1 _a'_acute__ + .byte $00 ; 226/e2 _a^_circum_ + .byte $00 ; 227/e3 _a~_tilde__ + .byte $00 ; 228/e4 _a"_dieres_ + .byte $00 ; 229/e5 _a__ring___ + .byte $00 ; 230/e6 _ae________ + .byte $00 ; 231/e7 _c,cedilla_ + .byte $00 ; 232/e8 _e`_grave__ + .byte $00 ; 233/e9 _e'_acute__ + .byte $00 ; 234/ea _e^_circum_ + .byte $00 ; 235/eb _e"_dieres_ + .byte $00 ; 236/ec _i`_grave__ + .byte $00 ; 237/ed _i'_acute__ + .byte $00 ; 238/ee _i^_circum_ + .byte $00 ; 239/ef _i"_dieres_ + .byte $00 ; 240/f0 _o^x_Eth_s_ + .byte $00 ; 241/f1 _n~_tilda__ + .byte $00 ; 242/f2 _o`_grave__ + .byte $00 ; 243/f3 _o'_acute__ + .byte $00 ; 244/f4 _o^_circum_ + .byte $00 ; 245/f5 _o~_tilde__ + .byte $00 ; 246/f6 _o"_dieres_ + .byte $00 ; 247/f7 __divide___ + .byte $00 ; 248/f8 _o/_slash__ + .byte $00 ; 249/f9 _u`_grave__ + .byte $00 ; 250/fa _u'_acute__ + .byte $00 ; 251/fb _u^_circum_ + .byte $00 ; 252/fc _u"_dieres_ + .byte $00 ; 253/fd _y'_acute__ + .byte $00 ; 254/fe _sm_thorn__ + .byte $00 ; 255/ff _y"_dieres_ diff --git a/libsrc/osic1p/cvline.s b/libsrc/osic1p/cvline.s new file mode 100644 index 000000000..84e5a45bf --- /dev/null +++ b/libsrc/osic1p/cvline.s @@ -0,0 +1,29 @@ +; +; based on CBM version +; originally by: +; Ullrich von Bassewitz, 08.08.1998 +; +; void cvlinexy (unsigned char x, unsigned char y, unsigned char length); +; void cvline (unsigned char length); +; + + .export _cvlinexy, _cvline + .import popa, _gotoxy, putchar, newline + .importzp tmp1 + +_cvlinexy: + pha ; Save the length + jsr popa ; Get y + jsr _gotoxy ; Call this one, will pop params + pla ; Restore the length and run into _cvline + +_cvline: + cmp #0 ; Is the length zero? + beq L9 ; Jump if done + sta tmp1 +L1: lda #$95 ; Vertical bar + jsr putchar ; Write, no cursor advance + jsr newline ; Advance cursor to next line + dec tmp1 + bne L1 +L9: rts diff --git a/libsrc/osic1p/extra/screen-s3-32x28.s b/libsrc/osic1p/extra/screen-s3-32x28.s new file mode 100644 index 000000000..40ed24203 --- /dev/null +++ b/libsrc/osic1p/extra/screen-s3-32x28.s @@ -0,0 +1,16 @@ +; +; Implementation of screen-layout related functions for Superboard /// +; + + .include "../osiscreen.inc" + +S3_SCR_BASE := $D000 ; Base of Superboard /// video RAM +S3_VRAM_SIZE = $0400 ; Size of Superboard /// video RAM (1 kB) +S3_SCR_WIDTH = $20 ; Screen width +S3_SCR_HEIGHT = $1C ; Screen height +S3_SCR_FIRSTCHAR = $80 ; Offset of cursor position (0, 0) from base + ; of video RAM +S3_SCROLL_DIST = $20 ; Memory distance for scrolling by one line + +osi_screen_funcs S3_SCR_BASE, S3_VRAM_SIZE, S3_SCR_FIRSTCHAR, \ + S3_SCR_WIDTH, S3_SCR_HEIGHT, S3_SCROLL_DIST diff --git a/libsrc/osic1p/extzp.inc b/libsrc/osic1p/extzp.inc new file mode 100644 index 000000000..5e85e0b74 --- /dev/null +++ b/libsrc/osic1p/extzp.inc @@ -0,0 +1,7 @@ +; +; Additional zero page locations for the Challenger 1P. +; + +; ------------------------------------------------------------------------ + + .globalzp CURS_X, CURS_Y, SCREEN_PTR, CHARBUF diff --git a/libsrc/osic1p/extzp.s b/libsrc/osic1p/extzp.s new file mode 100644 index 000000000..b3bdaa0b7 --- /dev/null +++ b/libsrc/osic1p/extzp.s @@ -0,0 +1,20 @@ +; +; Additional zero page locations for the Challenger 1P. +; NOTE: The zeropage locations contained in this file get initialized +; in the startup code, so if you change anything here, be sure to check +; not only the linker config, but also the startup file. +; + +; ------------------------------------------------------------------------ + + .include "extzp.inc" + +.segment "EXTZP" : zeropage + +CURS_X: .res 1 +CURS_Y: .res 1 +SCREEN_PTR: .res 2 +CHARBUF: .res 1 + +; size 5 +; Adjust size of the ZP segment in osic1p.cfg if the size changes diff --git a/libsrc/osic1p/gotox.s b/libsrc/osic1p/gotox.s new file mode 100644 index 000000000..0dea72b9a --- /dev/null +++ b/libsrc/osic1p/gotox.s @@ -0,0 +1,13 @@ +; +; copied from CBM implementation +; originally by: +; Ullrich von Bassewitz, 07.08.1998 +; +; void gotox (unsigned char x); +; + .export _gotox + .import plot + .include "extzp.inc" + +_gotox: sta CURS_X ; Set new position + jmp plot ; And activate it diff --git a/libsrc/osic1p/gotoxy.s b/libsrc/osic1p/gotoxy.s new file mode 100644 index 000000000..f76537349 --- /dev/null +++ b/libsrc/osic1p/gotoxy.s @@ -0,0 +1,17 @@ +; +; copied from CBM implementation +; +; originally by: +; Ullrich von Bassewitz, 06.08.1998 +; +; void gotoxy (unsigned char x, unsigned char y); +; + .export _gotoxy + .import popa, plot + .include "extzp.inc" + +_gotoxy: + sta CURS_Y ; Set Y + jsr popa ; Get X + sta CURS_X ; Set X + jmp plot ; Set the cursor position diff --git a/libsrc/osic1p/gotoy.s b/libsrc/osic1p/gotoy.s new file mode 100644 index 000000000..693863d94 --- /dev/null +++ b/libsrc/osic1p/gotoy.s @@ -0,0 +1,13 @@ +; +; copied from CBM implementation +; originally by: +; Ullrich von Bassewitz, 0.08.1998 +; +; void gotoy (unsigned char y); +; + .export _gotoy + .import plot + .include "extzp.inc" + +_gotoy: sta CURS_Y ; Set the new position + jmp plot ; And activate it diff --git a/libsrc/osic1p/kbhit.s b/libsrc/osic1p/kbhit.s new file mode 100644 index 000000000..b616b4a3f --- /dev/null +++ b/libsrc/osic1p/kbhit.s @@ -0,0 +1,47 @@ +; +; unsigned char kbhit (void); +; +; The method to detect a pressed key is based on the documentation in +; "Section 3 Programmed Key Functions" in "The Challenger Character Graphics +; Reference Manual" +; We only want to return true for characters that can be returned by cgetc(), +; but not for keys like <Shift> or <Ctrl>. Therefore a special handling is +; needed for the first row. This is implemented by a bit mask that is stored +; in tmp1 and that is set to zero after the first round. +; + + .export _kbhit + .include "osic1p.inc" + .include "extzp.inc" + .include "zeropage.inc" + +_kbhit: + lda #%11011111 ; Mask for only checking the column for the + sta tmp1 ; ESC key in the first keyboard row. + + lda #%11111110 ; Mask for first keyboard row +scan: + sta KBD ; Select keyboard row + tax ; Save A + lda KBD ; Read keyboard columns + ora tmp1 ; Mask out uninteresting keys (only relevant in + ; first row) + cmp #$FF ; No keys pressed? + bne keypressed + lda #$00 ; For remaining rows no keys masked + sta tmp1 + txa ; Restore A + sec ; Want to shift in ones + rol a ; Rotate row select to next bit position + cmp #$FF ; Done? + bne scan ; If not, continue + lda #$00 ; Return false + tax ; High byte of return is also zero + sta CHARBUF ; No character in buffer + rts +keypressed: + jsr INPUTC ; Get input character in A + sta CHARBUF ; Save in buffer + ldx #$00 ; High byte of return is always zero + lda #$01 ; Return true + rts diff --git a/libsrc/osic1p/oserror.s b/libsrc/osic1p/oserror.s new file mode 100644 index 000000000..073691a06 --- /dev/null +++ b/libsrc/osic1p/oserror.s @@ -0,0 +1,20 @@ +; +; dummy implementation for Challenger 1P based on atmos implementation +; +; original by +; Stefan Haubenthal, 2011-04-18 +; +; int __fastcall__ _osmaperrno (unsigned char oserror); +; /* Map a system specific error into a system independent code */ +; + + .include "errno.inc" + .export __osmaperrno + +.proc __osmaperrno + + lda #<EUNKNOWN + ldx #>EUNKNOWN + rts + +.endproc diff --git a/libsrc/osic1p/osic1p.inc b/libsrc/osic1p/osic1p.inc new file mode 100644 index 000000000..eabeaf79e --- /dev/null +++ b/libsrc/osic1p/osic1p.inc @@ -0,0 +1,4 @@ +; Addresses +INPUTC := $FD00 ; Input character from keyboard +RESET := $FF00 ; Reset address, show boot prompt +KBD := $DF00 ; Polled keyboard register diff --git a/libsrc/osic1p/osiscreen.inc b/libsrc/osic1p/osiscreen.inc new file mode 100644 index 000000000..66c5e9fb0 --- /dev/null +++ b/libsrc/osic1p/osiscreen.inc @@ -0,0 +1,184 @@ +; +; 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 popa ; Get Y + jsr _gotoxy ; Set cursor, drop x + 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 popa, _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/osic1p/screen-c1p-24x24.s b/libsrc/osic1p/screen-c1p-24x24.s new file mode 100644 index 000000000..e691c2f1f --- /dev/null +++ b/libsrc/osic1p/screen-c1p-24x24.s @@ -0,0 +1,16 @@ +; +; Implementation of screen-layout related functions for Challenger 1P +; + + .include "osiscreen.inc" + +C1P_SCR_BASE := $D000 ; Base of C1P video RAM +C1P_VRAM_SIZE = $0400 ; Size of C1P video RAM (1 kB) +C1P_SCR_WIDTH = $18 ; Screen width +C1P_SCR_HEIGHT = $18 ; Screen height +C1P_SCR_FIRSTCHAR = $85 ; Offset of cursor position (0, 0) from base + ; of video RAM +C1P_SCROLL_DIST = $20 ; Memory distance for scrolling by one line + +osi_screen_funcs C1P_SCR_BASE, C1P_VRAM_SIZE, C1P_SCR_FIRSTCHAR, \ + C1P_SCR_WIDTH, C1P_SCR_HEIGHT, C1P_SCROLL_DIST diff --git a/libsrc/osic1p/wherex.s b/libsrc/osic1p/wherex.s new file mode 100644 index 000000000..1155a8abd --- /dev/null +++ b/libsrc/osic1p/wherex.s @@ -0,0 +1,14 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; Copied from cbm/wherex.s + +; unsigned char wherex (void); +; + .export _wherex + .include "extzp.inc" + +.proc _wherex + lda CURS_X + ldx #$00 + rts +.endproc diff --git a/libsrc/osic1p/wherey.s b/libsrc/osic1p/wherey.s new file mode 100644 index 000000000..632cf4a15 --- /dev/null +++ b/libsrc/osic1p/wherey.s @@ -0,0 +1,14 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; Copied from cbm/wherey.s +; +; unsigned char wherey (void); +; + .export _wherey + .include "extzp.inc" + +.proc _wherey + lda CURS_Y + ldx #$00 + rts +.endproc diff --git a/libsrc/pce/_scrsize.s b/libsrc/pce/_scrsize.s new file mode 100644 index 000000000..038622a6f --- /dev/null +++ b/libsrc/pce/_scrsize.s @@ -0,0 +1,18 @@ +; +; Screen size variables +; + .include "pce.inc" + + .export screensize +screensize: + ldx xsize + ldy ysize + rts + +; FIXME: changing the video mode allows for different screen sizes + +.rodata + .export xsize, ysize + +xsize: .byte charsperline +ysize: .byte screenrows diff --git a/libsrc/pce/chline.s b/libsrc/pce/chline.s new file mode 100644 index 000000000..8bf8f1626 --- /dev/null +++ b/libsrc/pce/chline.s @@ -0,0 +1,32 @@ +; +; Ullrich von Bassewitz, 08.08.1998 +; +; void chlinexy (unsigned char x, unsigned char y, unsigned char length); +; void chline (unsigned char length); +; + + .export _chlinexy, _chline + .import popa, _gotoxy, cputdirect + .importzp tmp1 + + .include "pce.inc" + +_chlinexy: + pha ; Save the length + jsr popa ; Get y + jsr _gotoxy ; Call this one, will pop params + pla ; Restore the length + +_chline: + cmp #0 ; Is the length zero? + beq L9 ; Jump if done + sta tmp1 +L1: lda #CH_HLINE ; Horizontal line, screen code + jsr cputdirect ; Direct output + dec tmp1 + bne L1 +L9: rts + + + + diff --git a/libsrc/pce/clock.s b/libsrc/pce/clock.s new file mode 100644 index 000000000..261739df8 --- /dev/null +++ b/libsrc/pce/clock.s @@ -0,0 +1,33 @@ +; +; clock_t clock (void); +; + + .include "pce.inc" + .include "extzp.inc" + + .export _clock + .forceimport ticktock + .importzp sreg + .constructor initclock + + +.proc _clock + + lda tickcount+3 + sta sreg+1 + lda tickcount+2 + sta sreg + ldx tickcount+1 + lda tickcount + rts + +.endproc + + .segment "INIT" +initclock: + lda #0 + ldx #3 +@lp: sta tickcount,x + dex + bpl @lp + rts diff --git a/libsrc/pce/clrscr.s b/libsrc/pce/clrscr.s new file mode 100644 index 000000000..e3f40bb8b --- /dev/null +++ b/libsrc/pce/clrscr.s @@ -0,0 +1,38 @@ + + .include "pce.inc" + .include "extzp.inc" + + .import plot + .export _clrscr +_clrscr: + + st0 #VDC_MAWR + st1 #<$0000 + st2 #>$0000 + + st0 #VDC_VWR + ldy #$40 +rowloop: + ldx #$80 +colloop: + lda #' ' + sta a:VDC_DATA_LO + lda #$02 + sta a:VDC_DATA_HI + + dex + bne colloop + dey + bne rowloop + +; Go to the home position. + + stz CURS_X + stz CURS_Y + jmp plot + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import initconio +conio_init = initconio diff --git a/libsrc/pce/color.s b/libsrc/pce/color.s new file mode 100644 index 000000000..0ff991a2e --- /dev/null +++ b/libsrc/pce/color.s @@ -0,0 +1,66 @@ +; +; unsigned char __fastcall__ textcolor (unsigned char color); +; unsigned char __fastcall__ bgcolor (unsigned char color); +; unsigned char __fastcall__ bordercolor (unsigned char color); +; + + + .export _textcolor, _bgcolor, _bordercolor + + .include "pce.inc" + .include "extzp.inc" + +_textcolor: + ldx CHARCOLOR ; get old value + sta CHARCOLOR ; set new value + txa + rts + +_bgcolor: + ldx BGCOLOR ; get old value + sta BGCOLOR ; set new value + asl a + tay + + stz VCE_ADDR_LO + stz VCE_ADDR_HI + lda colors,y + sta VCE_DATA_LO + lda colors+1,y + sta VCE_DATA_HI + + txa + rts + +_bordercolor: + lda #0 + tax + rts + + .rodata + .export colors + +colors: + ; G R B + .word ((0<<6)+(0<<3)+(0)) ; 0 black + .word ((7<<6)+(7<<3)+(7)) ; 1 white + .word ((0<<6)+(7<<3)+(0)) ; 2 red + .word ((7<<6)+(0<<3)+(7)) ; 3 cyan + .word ((0<<6)+(5<<3)+(7)) ; 4 violett + .word ((7<<6)+(0<<3)+(0)) ; 5 green + .word ((0<<6)+(0<<3)+(7)) ; 6 blue + .word ((7<<6)+(7<<3)+(0)) ; 7 yellow + .word ((5<<6)+(7<<3)+(0)) ; 8 orange + .word ((3<<6)+(4<<3)+(3)) ; 9 brown + .word ((4<<6)+(7<<3)+(4)) ; a light red + .word ((3<<6)+(3<<3)+(3)) ; b dark grey + .word ((4<<6)+(4<<3)+(4)) ; c middle grey + .word ((7<<6)+(4<<3)+(4)) ; d light green + .word ((4<<6)+(4<<3)+(7)) ; e light blue + .word ((6<<6)+(6<<3)+(6)) ; f light gray + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import initconio +conio_init = initconio diff --git a/libsrc/pce/conio.s b/libsrc/pce/conio.s new file mode 100644 index 000000000..b2bb0f9d5 --- /dev/null +++ b/libsrc/pce/conio.s @@ -0,0 +1,117 @@ + .include "pce.inc" + .include "extzp.inc" + + .import vce_init + .import psg_init + .import colors + .importzp ptr1, tmp1 + + .constructor initconio + + .macpack longbranch + + .segment "INIT" +initconio: + jsr vce_init + jsr psg_init + jsr conio_init + jsr set_palette + + st0 #VDC_CR + st1 #<$0088 + st2 #>$0088 + rts + +set_palette: + stz VCE_ADDR_LO + stz VCE_ADDR_HI + + ldx #0 +@lp: + ldy #16 +@lp1: + lda colors,x + sta VCE_DATA_LO + lda colors+1,x + sta VCE_DATA_HI + dey + bne @lp1 + + inx + inx + cpx #16*2 + jne @lp + + stz VCE_ADDR_LO + stz VCE_ADDR_HI + stz VCE_DATA_LO + stz VCE_DATA_HI + + rts + +conio_init: + ; Load font + st0 #VDC_MAWR + st1 #<$2000 + st2 #>$2000 + + ; ptr to font data + lda #<font + sta ptr1 + lda #>font + sta ptr1+1 + + st0 #VDC_VWR ; VWR + + lda #0 + sta tmp1 + jsr copy + + lda #<font + sta ptr1 + lda #>font + sta ptr1+1 + + lda #$ff + sta tmp1 + jsr copy + + ldx #0 + stx BGCOLOR + inx + stx CHARCOLOR + + rts + +copy: + ldy #$80 ; 128 chars +charloop: + ldx #$08 ; 8 bytes/char +lineloop: + lda (ptr1) + eor tmp1 + sta a:VDC_DATA_LO ; bitplane 0 + stz a:VDC_DATA_HI ; bitplane 1 + + clc ; increment font pointer + lda ptr1 + adc #$01 + sta ptr1 + lda ptr1+1 + adc #$00 + sta ptr1+1 + dex + bne lineloop ; next bitplane 0 byte + ldx #$08 ; fill bitplane 2/3 with 0 +fillloop: + st1 #$00 + st2 #$00 + dex + bne fillloop ; next byte + dey + bne charloop ; next character + + rts + +font: + .include "vga.inc" diff --git a/libsrc/pce/cputc.s b/libsrc/pce/cputc.s new file mode 100644 index 000000000..8d1cec8eb --- /dev/null +++ b/libsrc/pce/cputc.s @@ -0,0 +1,99 @@ +; +; void cputcxy (unsigned char x, unsigned char y, char c); +; void cputc (char c); +; + + .export _cputcxy, _cputc, cputdirect, putchar + .export newline, plot + .import popa, _gotoxy + .import PLOT + .import xsize + + .importzp tmp3,tmp4 + + .include "pce.inc" + .include "extzp.inc" + +_cputcxy: + pha ; Save C + jsr popa ; Get Y + jsr _gotoxy ; Set cursor, drop x + pla ; Restore C + +; Plot a character - also used as internal function + +_cputc: cmp #$0d ; CR? + bne L1 + lda #0 + sta CURS_X + beq plot ; Recalculate pointers + +L1: cmp #$0a ; LF? + beq newline ; Recalculate pointers + +; Printable char of some sort + +cputdirect: + jsr putchar ; Write the character to the screen + +; Advance cursor position + +advance: + ldy CURS_X + iny + cpy xsize + bne L3 + jsr newline ; new line + ldy #0 ; + cr +L3: sty CURS_X + jmp plot + +newline: + inc CURS_Y + +; Set cursor position, calculate RAM pointers + +plot: ldy CURS_X + ldx CURS_Y + clc + jmp PLOT ; Set the new cursor + +; Write one character to the screen without doing anything else, return X +; position in Y + +putchar: + + ora RVS ; Set revers bit + + tax + + st0 #VDC_MAWR ; Memory Adress Write + + lda SCREEN_PTR + sta a:VDC_DATA_LO + + lda SCREEN_PTR + 1 + sta a:VDC_DATA_HI + + st0 #VDC_VWR ; VWR + + txa + sta a:VDC_DATA_LO ; character + + lda CHARCOLOR + + asl a + asl a + asl a + asl a + + ora #$02 + sta a:VDC_DATA_HI + + rts + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import initconio +conio_init = initconio diff --git a/libsrc/pce/crt0.s b/libsrc/pce/crt0.s new file mode 100644 index 000000000..e92e9eca3 --- /dev/null +++ b/libsrc/pce/crt0.s @@ -0,0 +1,142 @@ +; +; Startup code for cc65 (PCEngine version) +; +; by Groepaz/Hitmen <groepaz@gmx.net> +; based on code by Ullrich von Bassewitz <uz@cc65.org> +; +; This must be the *first* file on the linker command line +; + + .export _exit + .export __STARTUP__ : absolute = 1 ; Mark as startup + + .import initlib, donelib + .import push0, _main, zerobss + .import initheap + .import IRQStub + + ; Linker generated + .import __RAM_START__, __RAM_SIZE__ + .import __ROM0_START__, __ROM0_SIZE__ + .import __ROM_START__, __ROM_SIZE__ + .import __STARTUP_LOAD__,__STARTUP_RUN__, __STARTUP_SIZE__ + .import __CODE_LOAD__,__CODE_RUN__, __CODE_SIZE__ + .import __RODATA_LOAD__,__RODATA_RUN__, __RODATA_SIZE__ + .import __DATA_LOAD__,__DATA_RUN__, __DATA_SIZE__ + .import __BSS_SIZE__ + + .include "pce.inc" + .include "extzp.inc" + + .importzp sp + .importzp ptr1,ptr2 + .importzp tmp1,tmp2,tmp3 + +; ------------------------------------------------------------------------ +; Place the startup code in a special segment. + + .segment "STARTUP" + +start: + + ; setup the CPU and System-IRQ + + ; Initialize CPU + + sei + nop + csh ; set high speed CPU mode + nop + cld + nop + + ; Setup stack and memory mapping + ldx #$FF ; Stack top ($21FF) + txs + + ; at startup all MPRs are set to 0, so init them + lda #$ff + tam #%00000001 ; 0000-1FFF = Hardware page + lda #$F8 + tam #%00000010 ; 2000-3FFF = Work RAM + + ; FIXME: setup a larger block of memory to use with C-code + ;lda #$F7 + ;tam #%00000100 ; 4000-5FFF = Save RAM + ;lda #1 + ;tam #%00001000 ; 6000-7FFF Page 2 + ;lda #2 + ;tam #%00010000 ; 8000-9FFF Page 3 + ;lda #3 + ;tam #%00100000 ; A000-BFFF Page 4 + ;lda #4 + ;tam #%01000000 ; C000-DFFF Page 5 + ;lda #0 + ;tam #%10000000 ; e000-fFFF hucard/syscard bank 0 + + ; Clear work RAM (2000-3FFF) + stz <$00 + tii $2000, $2001, $1FFF + + ; Initialize hardware + stz TIMER_CTRL ; Timer off + lda #$07 + sta IRQ_MASK ; Interrupts off + stz IRQ_STATUS ; Acknowledge timer + + ; FIXME; i dont know why the heck this one doesnt work when called from a constructor :/ + .import vdc_init + jsr vdc_init + + ; Turn on background and VD interrupt/IRQ1 + lda #$05 + sta IRQ_MASK ; IRQ1=on + + ; Clear the BSS data + jsr zerobss + + ; Copy the .data segment to RAM + tii __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ + + ; setup the stack + lda #<(__RAM_START__+__RAM_SIZE__) + sta sp + lda #>(__RAM_START__+__RAM_SIZE__) + sta sp + 1 + + ; Call module constructors + jsr initlib + + cli ; allow IRQ only after constructors have run + + ; Pass an empty command line + jsr push0 ; argc + jsr push0 ; argv + + ldy #4 ; Argument size + jsr _main ; call the users code + + ; Call module destructors. This is also the _exit entry. +_exit: + jsr donelib ; Run module destructors + + ; reset the PCEngine (start over) + jmp start + +_nmi: + rti + + .export initmainargs +initmainargs: + rts + +; ------------------------------------------------------------------------ +; hardware vectors +; ------------------------------------------------------------------------ + .segment "VECTORS" + + .word IRQStub ; $fff6 IRQ2 (External IRQ, BRK) + .word IRQStub ; $fff8 IRQ1 (VDC) + .word IRQStub ; $fffa Timer + .word _nmi ; $fffc NMI + .word start ; $fffe reset diff --git a/libsrc/pce/ctype.s b/libsrc/pce/ctype.s new file mode 100644 index 000000000..fa9a65c8b --- /dev/null +++ b/libsrc/pce/ctype.s @@ -0,0 +1,161 @@ +; +; Stefan Haubenthal with minor changes from Ullrich von Bassewitz, 2003-05-02 +; +; Character specification table. +; + + .include "ctype.inc" + +; The tables are readonly, put them into the rodata segment + +.rodata + +; The following 256 byte wide table specifies attributes for the isxxx type +; of functions. Doing it by a table means some overhead in space, but it +; has major advantages: +; +; * It is fast. If it were'nt for the slow parameter passing of cc65, one +; could even define macros for the isxxx functions (this is usually +; done on other platforms). +; +; * It is highly portable. The only unportable part is the table itself, +; all real code goes into the common library. +; +; * We save some code in the isxxx functions. + + +__ctype: + .repeat 2 + .byte CT_CTRL ; 0/00 ___ctrl_@___ + .byte CT_CTRL ; 1/01 ___ctrl_A___ + .byte CT_CTRL ; 2/02 ___ctrl_B___ + .byte CT_CTRL ; 3/03 ___ctrl_C___ + .byte CT_CTRL ; 4/04 ___ctrl_D___ + .byte CT_CTRL ; 5/05 ___ctrl_E___ + .byte CT_CTRL ; 6/06 ___ctrl_F___ + .byte CT_CTRL ; 7/07 ___ctrl_G___ + .byte CT_CTRL ; 8/08 ___ctrl_H___ + .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB + ; 9/09 ___ctrl_I___ + .byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___ + .byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___ + .byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___ + .byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___ + .byte CT_CTRL ; 14/0e ___ctrl_N___ + .byte CT_CTRL ; 15/0f ___ctrl_O___ + .byte CT_CTRL ; 16/10 ___ctrl_P___ + .byte CT_CTRL ; 17/11 ___ctrl_Q___ + .byte CT_CTRL ; 18/12 ___ctrl_R___ + .byte CT_CTRL ; 19/13 ___ctrl_S___ + .byte CT_CTRL ; 20/14 ___ctrl_T___ + .byte CT_CTRL ; 21/15 ___ctrl_U___ + .byte CT_CTRL ; 22/16 ___ctrl_V___ + .byte CT_CTRL ; 23/17 ___ctrl_W___ + .byte CT_CTRL ; 24/18 ___ctrl_X___ + .byte CT_CTRL ; 25/19 ___ctrl_Y___ + .byte CT_CTRL ; 26/1a ___ctrl_Z___ + .byte CT_CTRL ; 27/1b ___ctrl_[___ + .byte CT_CTRL ; 28/1c ___ctrl_\___ + .byte CT_CTRL ; 29/1d ___ctrl_]___ + .byte CT_CTRL ; 30/1e ___ctrl_^___ + .byte CT_CTRL ; 31/1f ___ctrl_____ + .byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___ + .byte CT_NONE ; 33/21 _____!_____ + .byte CT_NONE ; 34/22 _____"_____ + .byte CT_NONE ; 35/23 _____#_____ + .byte CT_NONE ; 36/24 _____$_____ + .byte CT_NONE ; 37/25 _____%_____ + .byte CT_NONE ; 38/26 _____&_____ + .byte CT_NONE ; 39/27 _____'_____ + .byte CT_NONE ; 40/28 _____(_____ + .byte CT_NONE ; 41/29 _____)_____ + .byte CT_NONE ; 42/2a _____*_____ + .byte CT_NONE ; 43/2b _____+_____ + .byte CT_NONE ; 44/2c _____,_____ + .byte CT_NONE ; 45/2d _____-_____ + .byte CT_NONE ; 46/2e _____._____ + .byte CT_NONE ; 47/2f _____/_____ + .byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____ + .byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____ + .byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____ + .byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____ + .byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____ + .byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____ + .byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____ + .byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____ + .byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____ + .byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____ + .byte CT_NONE ; 58/3a _____:_____ + .byte CT_NONE ; 59/3b _____;_____ + .byte CT_NONE ; 60/3c _____<_____ + .byte CT_NONE ; 61/3d _____=_____ + .byte CT_NONE ; 62/3e _____>_____ + .byte CT_NONE ; 63/3f _____?_____ + + .byte CT_NONE ; 64/40 _____@_____ + .byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____ + .byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____ + .byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____ + .byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____ + .byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____ + .byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____ + .byte CT_UPPER ; 71/47 _____G_____ + .byte CT_UPPER ; 72/48 _____H_____ + .byte CT_UPPER ; 73/49 _____I_____ + .byte CT_UPPER ; 74/4a _____J_____ + .byte CT_UPPER ; 75/4b _____K_____ + .byte CT_UPPER ; 76/4c _____L_____ + .byte CT_UPPER ; 77/4d _____M_____ + .byte CT_UPPER ; 78/4e _____N_____ + .byte CT_UPPER ; 79/4f _____O_____ + .byte CT_UPPER ; 80/50 _____P_____ + .byte CT_UPPER ; 81/51 _____Q_____ + .byte CT_UPPER ; 82/52 _____R_____ + .byte CT_UPPER ; 83/53 _____S_____ + .byte CT_UPPER ; 84/54 _____T_____ + .byte CT_UPPER ; 85/55 _____U_____ + .byte CT_UPPER ; 86/56 _____V_____ + .byte CT_UPPER ; 87/57 _____W_____ + .byte CT_UPPER ; 88/58 _____X_____ + .byte CT_UPPER ; 89/59 _____Y_____ + .byte CT_UPPER ; 90/5a _____Z_____ + .byte CT_NONE ; 91/5b _____[_____ + .byte CT_NONE ; 92/5c _____\_____ + .byte CT_NONE ; 93/5d _____]_____ + .byte CT_NONE ; 94/5e _____^_____ + .byte CT_NONE ; 95/5f _UNDERLINE_ + .byte CT_NONE ; 96/60 ___grave___ + .byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____ + .byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____ + .byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____ + .byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____ + .byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____ + .byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____ + .byte CT_LOWER ; 103/67 _____g_____ + .byte CT_LOWER ; 104/68 _____h_____ + .byte CT_LOWER ; 105/69 _____i_____ + .byte CT_LOWER ; 106/6a _____j_____ + .byte CT_LOWER ; 107/6b _____k_____ + .byte CT_LOWER ; 108/6c _____l_____ + .byte CT_LOWER ; 109/6d _____m_____ + .byte CT_LOWER ; 110/6e _____n_____ + .byte CT_LOWER ; 111/6f _____o_____ + .byte CT_LOWER ; 112/70 _____p_____ + .byte CT_LOWER ; 113/71 _____q_____ + .byte CT_LOWER ; 114/72 _____r_____ + .byte CT_LOWER ; 115/73 _____s_____ + .byte CT_LOWER ; 116/74 _____t_____ + .byte CT_LOWER ; 117/75 _____u_____ + .byte CT_LOWER ; 118/76 _____v_____ + .byte CT_LOWER ; 119/77 _____w_____ + .byte CT_LOWER ; 120/78 _____x_____ + .byte CT_LOWER ; 121/79 _____y_____ + .byte CT_LOWER ; 122/7a _____z_____ + .byte CT_NONE ; 123/7b _____{_____ + .byte CT_NONE ; 124/7c _____|_____ + .byte CT_NONE ; 125/7d _____}_____ + .byte CT_NONE ; 126/7e _____~_____ + .byte CT_OTHER_WS ; 127/7f ____DEL____ + .endrepeat + + diff --git a/libsrc/pce/cvline.s b/libsrc/pce/cvline.s new file mode 100644 index 000000000..abd74a5c7 --- /dev/null +++ b/libsrc/pce/cvline.s @@ -0,0 +1,32 @@ +; +; Ullrich von Bassewitz, 08.08.1998 +; +; void cvlinexy (unsigned char x, unsigned char y, unsigned char length); +; void cvline (unsigned char length); +; + + .export _cvlinexy, _cvline + .import popa, _gotoxy, putchar, newline + .importzp tmp1 + + .include "pce.inc" + +_cvlinexy: + pha ; Save the length + jsr popa ; Get y + jsr _gotoxy ; Call this one, will pop params + pla ; Restore the length and run into _cvline + +_cvline: + cmp #0 ; Is the length zero? + beq L9 ; Jump if done + sta tmp1 +L1: lda #CH_VLINE ; Vertical bar + jsr putchar ; Write, no cursor advance + jsr newline ; Advance cursor to next line + dec tmp1 + bne L1 +L9: rts + + + diff --git a/libsrc/pce/extzp.inc b/libsrc/pce/extzp.inc new file mode 100644 index 000000000..dce91558f --- /dev/null +++ b/libsrc/pce/extzp.inc @@ -0,0 +1,18 @@ +; +; extzp.inc for the PC-Engine +; +; Groepaz/Hitmen, 2015-11-19 +; +; Assembler include file that imports the runtime zero page locations used +; by the PC-Engine runtime, ready for usage in asm code. +; + + + .global CURS_X: zp + .global CURS_Y: zp + .global SCREEN_PTR: zp + .global CHARCOLOR: zp + .global RVS: zp + .global BGCOLOR: zp + .global tickcount: zp + .global vdc_flags: zp diff --git a/libsrc/pce/extzp.s b/libsrc/pce/extzp.s new file mode 100644 index 000000000..26dc589b1 --- /dev/null +++ b/libsrc/pce/extzp.s @@ -0,0 +1,18 @@ +; +; Groepaz/Hitmen, 2015-11-19 +; +; zeropage locations for exclusive use by the library +; + + .include "extzp.inc" + + .segment "EXTZP" : zeropage + +CURS_X: .res 1 +CURS_Y: .res 1 +SCREEN_PTR: .res 2 +CHARCOLOR: .res 1 +RVS: .res 1 +BGCOLOR: .res 1 +tickcount: .res 4 +vdc_flags: .res 1 diff --git a/libsrc/pce/gotoxy.s b/libsrc/pce/gotoxy.s new file mode 100644 index 000000000..fb61646d1 --- /dev/null +++ b/libsrc/pce/gotoxy.s @@ -0,0 +1,22 @@ +; +; void gotoxy (unsigned char x, unsigned char y); +; + + .export _gotoxy + .import popa, plot + + .include "pce.inc" + .include "extzp.inc" + +_gotoxy: + sta CURS_Y ; Set Y + jsr popa ; Get X + sta CURS_X ; Set X + jmp plot ; Set the cursor position + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import initconio +conio_init = initconio + diff --git a/libsrc/pce/irq.s b/libsrc/pce/irq.s new file mode 100644 index 000000000..f34303d07 --- /dev/null +++ b/libsrc/pce/irq.s @@ -0,0 +1,48 @@ +; +; IRQ handling (PCE version) +; + + .export initirq, doneirq, IRQStub + + .import __INTERRUPTOR_COUNT__, callirq_y + + .include "pce.inc" + .include "extzp.inc" + +; ------------------------------------------------------------------------ +.segment "INIT" + +; a constructor +; +initirq: + rts + +; ------------------------------------------------------------------------ +.code + +; a destructor +; +doneirq: + rts + +; ------------------------------------------------------------------------ + +IRQStub: + phy + +; Save the display-source flags (and, release the interrupt). +; + ldy a:VDC_CTRL + sty vdc_flags + + ldy #<(__INTERRUPTOR_COUNT__ * 2) + beq @L1 + phx + pha + + jsr callirq_y + + pla + plx +@L1: ply + rti diff --git a/libsrc/pce/joy/pce-stdjoy.s b/libsrc/pce/joy/pce-stdjoy.s new file mode 100644 index 000000000..746929dd2 --- /dev/null +++ b/libsrc/pce/joy/pce-stdjoy.s @@ -0,0 +1,159 @@ + +; +; Standard joystick driver for the PCEngine +; + + .include "joy-kernel.inc" + .include "joy-error.inc" + .include "pce.inc" + + .macpack module + + +; ------------------------------------------------------------------------ +; Header. Includes jump table + + module_header _pce_stdjoy_joy + +; Driver signature + + .byte $6A, $6F, $79 ; "joy" + .byte JOY_API_VERSION ; Driver API version number + +; Library reference + + .addr $0000 + +; Button state masks (8 values) + + .byte $10 ; JOY_UP + .byte $40 ; JOY_DOWN + .byte $80 ; JOY_LEFT + .byte $20 ; JOY_RIGHT + .byte $01 ; JOY_FIRE_A + .byte $02 ; JOY_FIRE_B + .byte $04 ; JOY_SELECT + .byte $08 ; JOY_RUN + +; Jump table. + + .addr INSTALL + .addr UNINSTALL + .addr COUNT + .addr READJOY + .addr 0 ; IRQ entry unused + +; ------------------------------------------------------------------------ +; Constants + +JOY_COUNT = 4 ; Number of joysticks we support + + +.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 JOY_ERR_xx code in a/x. +; + +INSTALL: + lda #<JOY_ERR_OK + ldx #>JOY_ERR_OK + +; rts ; Run into UNINSTALL instead + +; ------------------------------------------------------------------------ +; DEINSTALL routine. Is called before the driver is removed from memory. +; Can do cleanup or whatever. Must not return anything. +; + +UNINSTALL: + rts + + +; ------------------------------------------------------------------------ +; COUNT: Return the total number of available joysticks in a/x. +; +;unsigned char __fastcall__ joy_count (void); + +COUNT: + lda #<JOY_COUNT + ldx #>JOY_COUNT + rts + +; ------------------------------------------------------------------------ +; READ: Read a particular joystick passed in A. +; +;unsigned char __fastcall__ joy_read (unsigned char joystick); + +READJOY: + pha + jsr read_joy + pla + tax ; Joystick number into X + + ; return value from buffer + +joy1: + lda padbuffer,x + ldx #0 + rts + +read_joy: + ; reset multitap counter + lda #$01 + sta JOY_CTRL + pha + pla + nop + nop + + lda #$03 + sta JOY_CTRL + pha + pla + nop + nop + + cly +nextpad: + lda #$01 + sta JOY_CTRL ; sel = 1 + pha + pla + nop ; some delay is required + nop + + lda JOY_CTRL + asl a + asl a + asl a + asl a + sta padbuffer, y ; store new value + + stz JOY_CTRL + pha + pla + + nop ; some delay is required + nop + + lda JOY_CTRL + and #$0F + ora padbuffer, y ; second half of new value + + eor #$FF + sta padbuffer, y ; store new value + + iny + cpy #$05 + bcc nextpad + rts + +.bss + +padbuffer: + .res 4 + diff --git a/libsrc/pce/joy_stat_stddrv.s b/libsrc/pce/joy_stat_stddrv.s new file mode 100644 index 000000000..2424c456b --- /dev/null +++ b/libsrc/pce/joy_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard joystick driver +; +; Oliver Schmidt, 2012-11-01 +; +; const void joy_static_stddrv[]; +; + + .export _joy_static_stddrv + .import _pce_stdjoy_joy + +.rodata + +_joy_static_stddrv := _pce_stdjoy_joy diff --git a/libsrc/pce/joy_stddrv.s b/libsrc/pce/joy_stddrv.s new file mode 100644 index 000000000..ba397409a --- /dev/null +++ b/libsrc/pce/joy_stddrv.s @@ -0,0 +1,13 @@ +; +; Name of the standard joystick driver +; +; Oliver Schmidt, 2012-11-01 +; +; const char joy_stddrv[]; +; + + .export _joy_stddrv + +.rodata + +_joy_stddrv: .asciiz "pce-stdjoy.joy" diff --git a/libsrc/pce/kplot.s b/libsrc/pce/kplot.s new file mode 100644 index 000000000..e4426d005 --- /dev/null +++ b/libsrc/pce/kplot.s @@ -0,0 +1,39 @@ + + .export PLOT + + .include "pce.inc" + .include "extzp.inc" + +PLOT: + bcs @getpos + + tya + ;clc ; already cleared + adc _plotlo,x + sta SCREEN_PTR + + lda _plothi,x + adc #0 + sta SCREEN_PTR+1 +@getpos: + ldx CURS_Y + ldy CURS_X + rts + + .rodata + +_plotlo: + .repeat screenrows,line + .byte <($0000+(line*$80)) + .endrepeat + +_plothi: + .repeat screenrows,line + .byte >($0000+(line*$80)) + .endrepeat + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import initconio +conio_init = initconio diff --git a/libsrc/pce/libref.s b/libsrc/pce/libref.s new file mode 100644 index 000000000..e4afa7eb1 --- /dev/null +++ b/libsrc/pce/libref.s @@ -0,0 +1,8 @@ +; +; Oliver Schmidt, 2013-05-31 +; + + .export joy_libref + .import _exit + +joy_libref := _exit diff --git a/libsrc/pce/memcpy.s b/libsrc/pce/memcpy.s new file mode 100644 index 000000000..40f831e30 --- /dev/null +++ b/libsrc/pce/memcpy.s @@ -0,0 +1,106 @@ +; +; This file, instead of "common/memcpy.s", will be assembled for the pce +; target. This version is smaller and faster because it uses the HuC6280's +; block-copy instructions. +; +; 2003-08-20, Ullrich von Bassewitz +; 2015-11-02, Greg King +; +; void* __fastcall__ memcpy (void* dest, const void* src, size_t size); +; +; NOTE: This function contains entry points for memmove(), which resorts to +; memcpy() for incrementing copies. The PC-Engine memset() uses this memcpy() +; to fill memory quickly. Don't change this module without looking at +; "pce/memmove.s" and "pce/memset.s"! +; + + .export _memcpy + .export memcpy_increment, memcpy_transfer, memcpy_getparams + + .import incsp2, popax + .importzp sp, ptr1, ptr2, ptr3 + + +; The structure of the transfer instructions + + .struct +opcode .byte +source .addr +destination .addr +length .word + .endstruct + +; ---------------------------------------------------------------------- +_memcpy: + jsr memcpy_getparams + +memcpy_increment: + ldy #$73 ; TII opcode + +memcpy_transfer: + sty transfer + opcode + + lda ptr1 + ldx ptr1+1 + sta transfer + source + stx transfer + source+1 + + lda ptr2 + ldx ptr2+1 + sta transfer + destination + stx transfer + destination+1 + + lda ptr3 + ldx ptr3+1 + sta transfer + length + stx transfer + length+1 + + jmp transfer + +; ---------------------------------------------------------------------- +; Get the parameters from the stack, as follows: +; +; size --> ptr3 +; src --> ptr1 +; dest --> ptr2 +; +; The first argument (dest) will remain on the stack; and, is returned in .XA! + +memcpy_getparams: + sta ptr3 + stx ptr3+1 ; save size + ora ptr3+1 + bne @L1 + +; The size is zero; copy nothing; just return the dest address. +; (The HuC6280's transfer instructions can't copy $0000 bytes; +; they would copy $10000 [64K] bytes instead.) + + ply ; drop return address + plx + jsr incsp2 ; drop src address + jmp popax ; get pointer; return it as result + +@L1: jsr popax + sta ptr1 + stx ptr1+1 ; save src + +; (Direct stack access is six cycles faster [total cycle count].) + + ldy #1 ; save dest + lda (sp),y ; get high byte + tax + lda (sp) ; get low byte + sta ptr2 + stx ptr2+1 + rts ; return dest address (for memmove) + +; ---------------------------------------------------------------------- +; The transfer instructions use inline arguments. +; Therefore, we must build the instruction, in the DATA segment. + +.data + +transfer: + tii $FFFF, $FFFF, $0001 + jmp popax ; get pointer; return it as result diff --git a/libsrc/pce/memmove.s b/libsrc/pce/memmove.s new file mode 100644 index 000000000..4b80da2af --- /dev/null +++ b/libsrc/pce/memmove.s @@ -0,0 +1,63 @@ +; +; This file, instead of "common/memmove.s", will be assembled for the pce +; target. This version is smaller and faster because it uses the HuC6280's +; block-copy instructions. +; +; 2003-08-20, Ullrich von Bassewitz +; 2015-10-23, Greg King +; +; void* __fastcall__ memmove (void* dest, const void* src, size_t size); +; +; NOTE: This function uses entry points from "pce/memcpy.s"! +; + + .export _memmove + + .import memcpy_getparams, memcpy_increment, memcpy_transfer + .importzp ptr1, ptr2, ptr3 + + .macpack generic + .macpack longbranch + + +; ---------------------------------------------------------------------- +_memmove: + jsr memcpy_getparams + +; Check for the copy direction. If dest < src, we must copy downwards (start +; at low addresses, and increase pointers); otherwise, we must copy upwards +; (start at high addresses, and decrease pointers). + + cmp ptr1 + txa + sbc ptr1+1 + jcc memcpy_increment ; Branch if dest < src + +; Copy decrementing; adjust the pointers to the end of the memory regions. + + lda ptr1 + add ptr3 + sta ptr1 + lda ptr1+1 + adc ptr3+1 + sta ptr1+1 + + lda ptr1 ; point to last byte of source + bne @L1 + dec ptr1+1 +@L1: dec ptr1 + + lda ptr2 + add ptr3 + sta ptr2 + lda ptr2+1 + adc ptr3+1 + sta ptr2+1 + + lda ptr2 ; point to last byte of target + bne @L2 + dec ptr2+1 +@L2: dec ptr2 + + ldy #$C3 ; TDD opcode + jmp memcpy_transfer diff --git a/libsrc/pce/memset.s b/libsrc/pce/memset.s new file mode 100644 index 000000000..45a78d533 --- /dev/null +++ b/libsrc/pce/memset.s @@ -0,0 +1,67 @@ +; +; This file, instead of "common/memset.s", will be assembled for the pce +; target. This version is smaller and faster because it uses a HuC6280 +; block-copy instruction. +; +; 1998-05-29, Ullrich von Bassewitz +; 2015-11-06, Greg King +; +; void* __fastcall__ _bzero (void* ptr, size_t n); +; void __fastcall__ bzero (void* ptr, size_t n); +; void* __fastcall__ memset (void* ptr, int c, size_t n); +; +; NOTE: bzero() will return its first argument, as memset() does. It is no +; problem to declare the return value as void, because it can be ignored. +; _bzero() (note the leading underscore) is declared with the proper +; return type because the compiler will replace memset() by _bzero() if +; the fill value is zero; and, the optimizer looks at the return type +; to see if the value in .XA is of any use. +; +; NOTE: This function uses entry points from "pce/memcpy.s"! +; + + .export __bzero, _bzero, _memset + + .import memcpy_getparams, memcpy_increment + .import pushax, popax + .importzp ptr1, ptr2, ptr3 + + .macpack longbranch + + +; ---------------------------------------------------------------------- +__bzero: +_bzero: pha + cla ; fill with zeros + jsr pushax ; (high byte isn't important) + pla + +_memset: + jsr memcpy_getparams + +; The fill byte is put at the beginning of the buffer; then, the buffer is +; copied to a second buffer that starts one byte above the start of the first +; buffer. Normally, we would use memmove() to avoid trouble; but here, we +; exploit that overlap, by using memcpy(). Therefore, the fill value is copied +; from each byte to the next byte, all the way to the end of the buffer. + + lda ptr1 ; get fill value + sta (ptr2) + + lda ptr3 ; count first byte + bne @L3 + dec ptr3+1 +@L3: dec a + sta ptr3 + ora ptr3+1 + jeq popax ; return ptr. if no more bytes + + lda ptr2 ; point to first buffer + ldx ptr2+1 + sta ptr1 + stx ptr1+1 + inc ptr2 ; point to second buffer + bne @L2 + inc ptr2+1 + +@L2: jmp memcpy_increment diff --git a/libsrc/pce/psg.s b/libsrc/pce/psg.s new file mode 100644 index 000000000..b1d610fa1 --- /dev/null +++ b/libsrc/pce/psg.s @@ -0,0 +1,30 @@ + .include "pce.inc" + + .export psg_init + + .segment "INIT" +psg_init: + clx + stz PSG_GLOBAL_PAN ; Clear global balance + +psg_clear_loop: + stx PSG_CHAN_SELECT ; Select channel + stz PSG_FREQ_LO ; Clear frequency LSB + stz PSG_FREQ_HI ; Clear frequency MSB + stz PSG_CHAN_CTRL ; Clear volume + stz PSG_CHAN_PAN ; Clear balance + stz PSG_NOISE ; Clear noise control + stz PSG_LFO_FREQ ; Clear LFO frequency + stz PSG_LFO_CTRL ; Clear LFO control + + cly +psg_clear_waveform: + stz PSG_CHAN_DATA ; Clear waveform byte + iny + cpy #$20 + bne psg_clear_waveform + + inx + cpx #$06 + bne psg_clear_loop + rts diff --git a/libsrc/pce/revers.s b/libsrc/pce/revers.s new file mode 100644 index 000000000..17a74508c --- /dev/null +++ b/libsrc/pce/revers.s @@ -0,0 +1,28 @@ + + .include "pce.inc" + .include "extzp.inc" + + .export _revers + +.proc _revers + + ldx #$00 ; Assume revers off + tay ; Test onoff + beq L1 ; Jump if off + ldx #$80 ; Load on value + ldy #$00 ; Assume old value is zero +L1: lda RVS ; Load old value + stx RVS ; Set new value + beq L2 ; Jump if old value zero + iny ; Make old value = 1 +L2: ldx #$00 ; Load high byte of result + tya ; Load low byte, set CC + rts + +.endproc + +;------------------------------------------------------------------------------- +; force the init constructor to be imported + + .import initconio +conio_init = initconio diff --git a/libsrc/pce/ticktock.s b/libsrc/pce/ticktock.s new file mode 100644 index 000000000..4e4d44d9a --- /dev/null +++ b/libsrc/pce/ticktock.s @@ -0,0 +1,18 @@ + .interruptor ticktock, 24 + + .include "pce.inc" + .include "extzp.inc" + +ticktock: + bbr5 vdc_flags,@s1 ; not vertical-blank interrupt + + ; Increment the system tick counter. + inc tickcount + bne @s1 + inc tickcount+1 + bne @s1 + inc tickcount+2 + bne @s1 + inc tickcount+3 + +@s1: rts diff --git a/libsrc/pce/vce.s b/libsrc/pce/vce.s new file mode 100644 index 000000000..af69c5ed1 --- /dev/null +++ b/libsrc/pce/vce.s @@ -0,0 +1,20 @@ + .include "pce.inc" + + .export vce_init + + .segment "INIT" +vce_init: + ; Set CTA to zero + stz VCE_ADDR_LO + stz VCE_ADDR_HI + ldy #$01 +vce_clear_bank: + ldx #$00 +vce_clear_color: + stz VCE_DATA_LO ; Clear color (LSB) + stz VCE_DATA_HI ; Clear color (MSB) + dex + bne vce_clear_color + dey + bne vce_clear_bank + rts diff --git a/libsrc/pce/vdc.s b/libsrc/pce/vdc.s new file mode 100644 index 000000000..878c79321 --- /dev/null +++ b/libsrc/pce/vdc.s @@ -0,0 +1,41 @@ + + .include "pce.inc" + +; FIXME: implement selection of different video modes at runtime +HIRES = 1 + + .export vdc_init + +vdc_init: + lda a:VDC_CTRL + + VREG $00, $0000 ; MAWR + VREG $01, $0000 ; MARR + VREG $05, $0000 ; CR + VREG $06, $0000 ; RCR + VREG $07, $0000 ; BXR + VREG $08, $0000 ; BYR + VREG $09, $0070 ; MAWR + VREG $0C, $1702 ; CRTC - VSR + VREG $0D, $00DF ; CRTC - VDS + VREG $0E, $000C ; CRTC - VDE + VREG $0F, $0000 ; DCR + +.if HIRES + + VREG $0A, $0C02 ; CRTC - HSR + VREG $0B, $043C ; CRTC - HDS + lda #$06 + sta VCE_CTRL + +.else + + VREG $0A, $0202 ; CRTC - HSR + VREG $0B, $041F ; CRTC - HDS + lda #$04 + sta VCE_CTRL + +.endif + + lda a:VDC_CTRL + rts diff --git a/libsrc/pce/vga.inc b/libsrc/pce/vga.inc new file mode 100644 index 000000000..9317d6ce4 --- /dev/null +++ b/libsrc/pce/vga.inc @@ -0,0 +1,220 @@ + +; VGA charset for the PC-Engine conio implementation + + .byte $00, $00, $00, $00, $00, $00, $00, $00 + + .byte %00000000 + .byte %00000000 + .byte %00000000 + .byte %11111111 + .byte %00000000 + .byte %00000000 + .byte %00000000 + .byte %00000000 + + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %11111111 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + + .byte %00000000 + .byte %00000000 + .byte %00000000 + .byte %00011111 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + + .byte %00000000 + .byte %00000000 + .byte %00000000 + .byte %11110000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00011111 + .byte %00000000 + .byte %00000000 + .byte %00000000 + .byte %00000000 + + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %11110000 + .byte %00000000 + .byte %00000000 + .byte %00000000 + .byte %00000000 + + .byte %00000000 + .byte %00000000 + .byte %00000000 + .byte %11111111 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %11111111 + .byte %00000000 + .byte %00000000 + .byte %00000000 + .byte %00000000 + + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00011111 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %11110000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + .byte %00010000 + + .byte $3C, $66, $66, $66, $3C, $18, $7E, $18 + .byte $3F, $33, $3F, $30, $30, $70, $F0, $E0 + .byte $7F, $63, $7F, $63, $63, $67, $E6, $C0 + .byte $99, $5A, $3C, $E7, $E7, $3C, $5A, $99 + .byte $80, $E0, $F8, $FE, $F8, $E0, $80, $00 + .byte $02, $0E, $3E, $FE, $3E, $0E, $02, $00 + .byte $18, $3C, $7E, $18, $18, $7E, $3C, $18 + .byte $66, $66, $66, $66, $66, $00, $66, $00 + .byte $7F, $DB, $DB, $7B, $1B, $1B, $1B, $00 + .byte $3E, $63, $38, $6C, $6C, $38, $CC, $78 + .byte $00, $00, $00, $00, $7E, $7E, $7E, $00 + .byte $18, $3C, $7E, $18, $7E, $3C, $18, $FF + .byte $18, $3C, $7E, $18, $18, $18, $18, $00 + .byte $18, $18, $18, $18, $7E, $3C, $18, $00 + .byte $00, $18, $0C, $FE, $0C, $18, $00, $00 + .byte $00, $30, $60, $FE, $60, $30, $00, $00 + .byte $00, $00, $C0, $C0, $C0, $FE, $00, $00 + .byte $00, $24, $66, $FF, $66, $24, $00, $00 + .byte $00, $18, $3C, $7E, $FF, $FF, $00, $00 + .byte $00, $FF, $FF, $7E, $3C, $18, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $00 + .byte $30, $78, $78, $78, $30, $00, $30, $00 + .byte $6C, $6C, $6C, $00, $00, $00, $00, $00 + .byte $6C, $6C, $FE, $6C, $FE, $6C, $6C, $00 + .byte $30, $7C, $C0, $78, $0C, $F8, $30, $00 + .byte $00, $C6, $CC, $18, $30, $66, $C6, $00 + .byte $38, $6C, $38, $76, $DC, $CC, $76, $00 + .byte $60, $60, $C0, $00, $00, $00, $00, $00 + .byte $18, $30, $60, $60, $60, $30, $18, $00 + .byte $60, $30, $18, $18, $18, $30, $60, $00 + .byte $00, $66, $3C, $FF, $3C, $66, $00, $00 + .byte $00, $30, $30, $FC, $30, $30, $00, $00 + .byte $00, $00, $00, $00, $00, $30, $30, $60 + .byte $00, $00, $00, $FC, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $30, $30, $00 + .byte $06, $0C, $18, $30, $60, $C0, $80, $00 + .byte $7C, $C6, $CE, $DE, $F6, $E6, $7C, $00 + .byte $30, $70, $30, $30, $30, $30, $FC, $00 + .byte $78, $CC, $0C, $38, $60, $CC, $FC, $00 + .byte $78, $CC, $0C, $38, $0C, $CC, $78, $00 + .byte $1C, $3C, $6C, $CC, $FE, $0C, $1E, $00 + .byte $FC, $C0, $F8, $0C, $0C, $CC, $78, $00 + .byte $38, $60, $C0, $F8, $CC, $CC, $78, $00 + .byte $FC, $CC, $0C, $18, $30, $30, $30, $00 + .byte $78, $CC, $CC, $78, $CC, $CC, $78, $00 + .byte $78, $CC, $CC, $7C, $0C, $18, $70, $00 + .byte $00, $30, $30, $00, $00, $30, $30, $00 + .byte $00, $30, $30, $00, $00, $30, $30, $60 + .byte $18, $30, $60, $C0, $60, $30, $18, $00 + .byte $00, $00, $FC, $00, $00, $FC, $00, $00 + .byte $60, $30, $18, $0C, $18, $30, $60, $00 + .byte $78, $CC, $0C, $18, $30, $00, $30, $00 + .byte $7C, $C6, $DE, $DE, $DE, $C0, $78, $00 + .byte $30, $78, $CC, $CC, $FC, $CC, $CC, $00 + .byte $FC, $66, $66, $7C, $66, $66, $FC, $00 + .byte $3C, $66, $C0, $C0, $C0, $66, $3C, $00 + .byte $F8, $6C, $66, $66, $66, $6C, $F8, $00 + .byte $7E, $60, $60, $78, $60, $60, $7E, $00 + .byte $7E, $60, $60, $78, $60, $60, $60, $00 + .byte $3C, $66, $C0, $C0, $CE, $66, $3E, $00 + .byte $CC, $CC, $CC, $FC, $CC, $CC, $CC, $00 + .byte $78, $30, $30, $30, $30, $30, $78, $00 + .byte $1E, $0C, $0C, $0C, $CC, $CC, $78, $00 + .byte $E6, $66, $6C, $78, $6C, $66, $E6, $00 + .byte $60, $60, $60, $60, $60, $60, $7E, $00 + .byte $C6, $EE, $FE, $FE, $D6, $C6, $C6, $00 + .byte $C6, $E6, $F6, $DE, $CE, $C6, $C6, $00 + .byte $38, $6C, $C6, $C6, $C6, $6C, $38, $00 + .byte $FC, $66, $66, $7C, $60, $60, $F0, $00 + .byte $78, $CC, $CC, $CC, $DC, $78, $1C, $00 + .byte $FC, $66, $66, $7C, $6C, $66, $E6, $00 + .byte $78, $CC, $E0, $70, $1C, $CC, $78, $00 + .byte $FC, $30, $30, $30, $30, $30, $30, $00 + .byte $CC, $CC, $CC, $CC, $CC, $CC, $FC, $00 + .byte $CC, $CC, $CC, $CC, $CC, $78, $30, $00 + .byte $C6, $C6, $C6, $D6, $FE, $EE, $C6, $00 + .byte $C6, $C6, $6C, $38, $38, $6C, $C6, $00 + .byte $CC, $CC, $CC, $78, $30, $30, $78, $00 + .byte $FE, $06, $0C, $18, $30, $60, $FE, $00 + .byte $78, $60, $60, $60, $60, $60, $78, $00 + .byte $C0, $60, $30, $18, $0C, $06, $02, $00 + .byte $78, $18, $18, $18, $18, $18, $78, $00 + .byte $10, $38, $6C, $C6, $00, $00, $00, $00 + .byte $00, $00, $00, $00, $00, $00, $00, $FF + .byte $30, $30, $18, $00, $00, $00, $00, $00 + .byte $00, $00, $78, $0C, $7C, $CC, $76, $00 + .byte $E0, $60, $60, $7C, $66, $66, $DC, $00 + .byte $00, $00, $78, $CC, $C0, $CC, $78, $00 + .byte $1C, $0C, $0C, $7C, $CC, $CC, $76, $00 + .byte $00, $00, $78, $CC, $FC, $C0, $78, $00 + .byte $38, $6C, $60, $F0, $60, $60, $F0, $00 + .byte $00, $00, $76, $CC, $CC, $7C, $0C, $F8 + .byte $E0, $60, $6C, $76, $66, $66, $E6, $00 + .byte $30, $00, $70, $30, $30, $30, $78, $00 + .byte $0C, $00, $0C, $0C, $0C, $CC, $CC, $78 + .byte $E0, $60, $66, $6C, $78, $6C, $E6, $00 + .byte $70, $30, $30, $30, $30, $30, $78, $00 + .byte $00, $00, $CC, $FE, $FE, $D6, $C6, $00 + .byte $00, $00, $F8, $CC, $CC, $CC, $CC, $00 + .byte $00, $00, $78, $CC, $CC, $CC, $78, $00 + .byte $00, $00, $DC, $66, $66, $7C, $60, $F0 + .byte $00, $00, $76, $CC, $CC, $7C, $0C, $1E + .byte $00, $00, $DC, $76, $66, $60, $F0, $00 + .byte $00, $00, $7C, $C0, $78, $0C, $F8, $00 + .byte $10, $30, $7C, $30, $30, $34, $18, $00 + .byte $00, $00, $CC, $CC, $CC, $CC, $76, $00 + .byte $00, $00, $CC, $CC, $CC, $78, $30, $00 + .byte $00, $00, $C6, $D6, $FE, $FE, $6C, $00 + .byte $00, $00, $C6, $6C, $38, $6C, $C6, $00 + .byte $00, $00, $CC, $CC, $CC, $7C, $0C, $F8 + .byte $00, $00, $FC, $98, $30, $64, $FC, $00 + .byte $1C, $30, $30, $E0, $30, $30, $1C, $00 + .byte $18, $18, $18, $00, $18, $18, $18, $00 + .byte $E0, $30, $30, $1C, $30, $30, $E0, $00 + .byte $76, $DC, $00, $00, $00, $00, $00, $00 + .byte $00, $10, $38, $6C, $C6, $C6, $FE, $00 diff --git a/libsrc/pce/waitvblank.s b/libsrc/pce/waitvblank.s new file mode 100644 index 000000000..b9f0f902f --- /dev/null +++ b/libsrc/pce/waitvblank.s @@ -0,0 +1,18 @@ +; +; void waitvblank (void); +; + + .include "pce.inc" + .include "extzp.inc" + + .forceimport ticktock + .export _waitvblank + +.proc _waitvblank + + lda tickcount +@lp: cmp tickcount + beq @lp + rts + +.endproc diff --git a/libsrc/pet/crt0.s b/libsrc/pet/crt0.s index 66aed0366..c1c805308 100644 --- a/libsrc/pet/crt0.s +++ b/libsrc/pet/crt0.s @@ -94,7 +94,7 @@ L2: lda zpsave,x ; ------------------------------------------------------------------------ -.segment "ZPSAVE" +.segment "INITBSS" zpsave: .res zpspace diff --git a/libsrc/pet/mainargs.s b/libsrc/pet/mainargs.s index 0d5b18987..8ba6e3117 100644 --- a/libsrc/pet/mainargs.s +++ b/libsrc/pet/mainargs.s @@ -12,7 +12,7 @@ MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name +NAME_LEN = 16 ; Maximum length of command-name ;--------------------------------------------------------------------------- @@ -25,24 +25,24 @@ NAME_LEN = 16 ; maximum length of command-name ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. -; Because the buffer, that we're copying into, was zeroed out, -; we don't need to add a NUL character. -; + + lda #0 ; The terminating NUL character ldy FNLEN cpy #NAME_LEN + 1 bcc L1 - ldy #NAME_LEN - 1 ; limit the length + ldy #NAME_LEN ; Limit the length + bne L1 ; Branch always L0: lda (FNADR),y - sta name,y -L1: dey +L1: sta name,y + dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. -; + ldx #0 L2: lda BASIC_BUF,x - beq done ; no "rem," no args. + beq done ; No "rem," no args. inx cmp #REM bne L2 @@ -54,7 +54,7 @@ next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces - beq next ; + beq next ; Found start of next argument. We've incremented the pointer in X already, so ; it points to the second character of the argument. This is useful since we @@ -111,14 +111,13 @@ done: lda #<argv .endproc -; These arrays are zeroed before initmainargs is called. -; char name[16+1]; -; char* argv[MAXARGS+1]={name}; -; -.bss +.segment "INITBSS" + term: .res 1 name: .res NAME_LEN + 1 .data + +; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 diff --git a/libsrc/pet/randomize.s b/libsrc/pet/randomize.s index fc5f621af..2c0fe722a 100644 --- a/libsrc/pet/randomize.s +++ b/libsrc/pet/randomize.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 05.11.2002 +; 2002-11-05, Ullrich von Bassewitz +; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ @@ -11,7 +12,7 @@ .include "pet.inc" __randomize: - ldx TIME + ldx TIME+2 lda TIME+1 ; Use 60HZ clock jmp _srand ; Initialize generator diff --git a/libsrc/plus4/crt0.s b/libsrc/plus4/crt0.s index b732459e0..ae3297562 100644 --- a/libsrc/plus4/crt0.s +++ b/libsrc/plus4/crt0.s @@ -195,7 +195,7 @@ spsave: .res 1 irqcount: .byte 0 -.segment "ZPSAVE" +.segment "INITBSS" zpsave: .res zpspace diff --git a/libsrc/plus4/mainargs.s b/libsrc/plus4/mainargs.s index 7df8402fe..59879978e 100644 --- a/libsrc/plus4/mainargs.s +++ b/libsrc/plus4/mainargs.s @@ -26,12 +26,11 @@ .import __argc, __argv .include "plus4.inc" - MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name +NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special INIT segment, ; which may be reused after the startup code is run @@ -42,24 +41,24 @@ initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. -; Because the buffer, that we're copying into, was zeroed out, -; we don't need to add a NUL character. -; + + lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 - ldy #NAME_LEN - 1 ; limit the length + ldy #NAME_LEN ; Limit the length + bne L1 ; Branch always L0: lda (FNAM),y - sta name,y -L1: dey +L1: sta name,y + dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. -; + ldx #0 L2: lda BASIC_BUF,x - beq done ; no "rem," no args. + beq done ; No "rem," no args. inx cmp #REM bne L2 @@ -71,7 +70,7 @@ next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces - beq next ; + beq next ; Found start of next argument. We've incremented the pointer in X already, so ; it points to the second character of the argument. This is useful since we @@ -125,17 +124,14 @@ done: lda #<argv sta __argv stx __argv + 1 rts - -; -------------------------------------------------------------------------- -; These arrays are zeroed before initmainargs is called. -; char name[16+1]; -; char* argv[MAXARGS+1]={name}; -; -.bss + +.segment "INITBSS" + term: .res 1 name: .res NAME_LEN + 1 .data + +; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 - diff --git a/libsrc/plus4/randomize.s b/libsrc/plus4/randomize.s index 6c7b86353..2a7f6a44b 100644 --- a/libsrc/plus4/randomize.s +++ b/libsrc/plus4/randomize.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 05.11.2002 +; 2002-11-05, Ullrich von Bassewitz +; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ @@ -12,6 +13,6 @@ __randomize: ldx TED_VLINELO ; Use TED rasterline as high byte - lda TIME ; Use 60HZ clock as low byte + lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/runtime/callmain.s b/libsrc/runtime/callmain.s index 83cd74482..0e6a84ebb 100644 --- a/libsrc/runtime/callmain.s +++ b/libsrc/runtime/callmain.s @@ -31,9 +31,9 @@ ;--------------------------------------------------------------------------- ; Data -.bss -__argc: .res 2 -__argv: .res 2 +.data +__argc: .word 0 +__argv: .addr 0 diff --git a/libsrc/runtime/stkchk.s b/libsrc/runtime/stkchk.s index 73df09917..6186fe4e2 100644 --- a/libsrc/runtime/stkchk.s +++ b/libsrc/runtime/stkchk.s @@ -101,14 +101,14 @@ Fail: lda #4 ; ---------------------------------------------------------------------------- ; Data -.bss +.segment "INITBSS" ; Initial stack pointer value. Stack is reset to this in case of overflows to ; allow program exit processing. -initialsp: .word 0 +initialsp: .res 2 ; Stack low water mark. -lowwater: .word 0 +lowwater: .res 2 diff --git a/libsrc/sim6502/errno.s b/libsrc/sim6502/errno.s deleted file mode 100644 index e6c2422c1..000000000 --- a/libsrc/sim6502/errno.s +++ /dev/null @@ -1,12 +0,0 @@ -; -; Oliver Schmidt, 2013-05-16 -; -; extern int errno; -; - - .include "errno.inc" - - .bss - -__errno: - .word 0 diff --git a/libsrc/vic20/crt0.s b/libsrc/vic20/crt0.s index e04881987..6a0f94a03 100644 --- a/libsrc/vic20/crt0.s +++ b/libsrc/vic20/crt0.s @@ -86,7 +86,7 @@ L2: lda zpsave,x ; ------------------------------------------------------------------------ -.segment "ZPSAVE" +.segment "INITBSS" zpsave: .res zpspace diff --git a/libsrc/vic20/mainargs.s b/libsrc/vic20/mainargs.s index eda8f4f85..a41a1c495 100644 --- a/libsrc/vic20/mainargs.s +++ b/libsrc/vic20/mainargs.s @@ -28,10 +28,9 @@ .include "vic20.inc" - MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code -NAME_LEN = 16 ; maximum length of command-name +NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special INIT segment, ; which may be reused after the startup code is run @@ -42,24 +41,24 @@ initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. -; Because the buffer, that we're copying into, was zeroed out, -; we don't need to add a NUL character. -; + + lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 - ldy #NAME_LEN - 1 ; limit the length + ldy #NAME_LEN ; Limit the length + bne L1 ; Branch always L0: lda (FNAM),y - sta name,y -L1: dey +L1: sta name,y + dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. -; + ldx #0 L2: lda BASIC_BUF,x - beq done ; no "rem," no args. + beq done ; No "rem," no args. inx cmp #REM bne L2 @@ -71,7 +70,7 @@ next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces - beq next ; + beq next ; Found start of next argument. We've incremented the pointer in X already, so ; it points to the second character of the argument. This is useful since we @@ -126,15 +125,13 @@ done: lda #<argv stx __argv + 1 rts -; These arrays are zeroed before initmainargs is called. -; char name[16+1]; -; char* argv[MAXARGS+1]={name}; -; -.bss +.segment "INITBSS" + term: .res 1 name: .res NAME_LEN + 1 .data + +; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 - diff --git a/libsrc/vic20/randomize.s b/libsrc/vic20/randomize.s index 8a1c4eee7..69cf07bb3 100644 --- a/libsrc/vic20/randomize.s +++ b/libsrc/vic20/randomize.s @@ -1,5 +1,6 @@ ; -; Ullrich von Bassewitz, 05.11.2002 +; 2002-11-05, Ullrich von Bassewitz +; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ @@ -16,6 +17,6 @@ __randomize: lda VIC_HLINE ; Get bit 1-8 of rasterline rol a ; Use bit 0-7 tax ; Use VIC rasterline as high byte - lda TIME ; Use 60HZ clock as low byte + lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator diff --git a/libsrc/zlib/uncompress.c b/libsrc/zlib/uncompress.c index 7810eb4f8..4e449a3ef 100644 --- a/libsrc/zlib/uncompress.c +++ b/libsrc/zlib/uncompress.c @@ -6,8 +6,8 @@ #include <zlib.h> -int uncompress (char* dest, unsigned* destLen, - const char* source, unsigned sourceLen) +int __fastcall__ uncompress (char* dest, unsigned* destLen, + const char* source, unsigned sourceLen) { unsigned len; unsigned char* ptr; diff --git a/samples/Makefile b/samples/Makefile index 79988ea70..951706ce6 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -44,7 +44,7 @@ endif C1541 = c1541 # -------------------------------------------------------------------------- -# System dependent settings +# System-dependent settings # The Apple machines need the start address adjusted when using TGI LDFLAGS_mandelbrot_apple2 = --start-addr 0x4000 @@ -81,10 +81,10 @@ LDFLAGS_tgidemo_atari = -D __RESERVED_MEMORY__=0x2000 .PRECIOUS: %.o .o: - @$(LD) $(LDFLAGS_$(basename $@)_$(SYS)) -o $@ -t $(SYS) -m $@.map $^ $(CLIB) + @$(LD) $(LDFLAGS_$(@F)_$(SYS)) -o $@ -t $(SYS) -m $@.map $^ $(CLIB) # -------------------------------------------------------------------------- -# List of executables. This list could be made target dependent by checking +# List of executables. This list could be made target-dependent by checking # $(SYS). EXELIST = ascii \ @@ -103,13 +103,23 @@ EXELIST = ascii \ tgidemo # -------------------------------------------------------------------------- -# Rules how to make each one of the binaries +# Rules to make the binaries .PHONY: all all: $(EXELIST) # -------------------------------------------------------------------------- -# Rule to make a disk with all samples. Needs the c1541 program that comes +# Overlay rules. Overlays need special ld65 configuration files. Also, the +# overlay file-names are shortenned to fit the Atari's 8.3-character limit. + +multdemo: multidemo.o + @$(LD) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(CLIB) + +ovrldemo: overlaydemo.o + @$(LD) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(CLIB) + +# -------------------------------------------------------------------------- +# Rule to make a CBM disk with all samples. Needs the c1541 program that comes # with the VICE emulator. .PHONY: disk @@ -125,7 +135,7 @@ samples.d64: all done # -------------------------------------------------------------------------- -# Cleanup rules +# Clean-up rules .PHONY: clean clean: @@ -134,3 +144,4 @@ clean: .PHONY: zap zap: clean $(RM) $(EXELIST) samples.d64 + $(RM) multdemo.? ovrldemo.? diff --git a/samples/README b/samples/README index 5997fc8d0..edd06ff02 100644 --- a/samples/README +++ b/samples/README @@ -11,6 +11,7 @@ Please note: the programs manually. * The makefile specifies the C64 as the default target platform, because all + but one of the programs run on this platform. When compiling for another platform, you will have to change the line that specifies the target system at the top of the makefile. diff --git a/samples/hello.c b/samples/hello.c index 90a1d4bdc..78c28af89 100644 --- a/samples/hello.c +++ b/samples/hello.c @@ -10,7 +10,7 @@ #include <stdlib.h> #include <string.h> #include <conio.h> -#include <dbg.h> +#include <joystick.h> @@ -68,15 +68,23 @@ int main (void) gotoxy ((XSize - strlen (Text)) / 2, YSize / 2); cprintf ("%s", Text); +#if defined(__NES__) || defined(__PCE__) + + /* Wait for the user to press a button */ + joy_install (joy_static_stddrv); + while (!joy_read (JOY_1)) ; + joy_uninstall (); + +#else + /* Wait for the user to press a key */ (void) cgetc (); +#endif + /* Clear the screen again */ clrscr (); /* Done */ return EXIT_SUCCESS; } - - - diff --git a/samples/mousetest.c b/samples/mousetest.c index 7d9409659..4a849cb98 100644 --- a/samples/mousetest.c +++ b/samples/mousetest.c @@ -40,44 +40,11 @@ -#if defined(__C64__) || defined(__C128__) || defined(__CBM510__) +#ifdef __CBM__ -/* Addresses of data for sprite 0 */ -#if defined(__C64__) -# define SPRITE0_DATA ((unsigned char[64])0x0340) -# define SPRITE0_PTR ((unsigned char *)0x07F8) -#elif defined(__C128__) -# define SPRITE0_DATA ((unsigned char[64])0x0E00) -# define SPRITE0_PTR ((unsigned char *)0x07F8) -#elif defined(__CBM510__) -# define SPRITE0_DATA ((unsigned char[64])0xF400) -# define SPRITE0_PTR ((unsigned char *)0xF3F8) -#endif +/* Set dark-on-light colors. */ +const unsigned char mouse_def_pointercolor = COLOR_BLACK; -/* The mouse sprite (an arrow) */ -static const unsigned char MouseSprite[64] = { - 0xFE, 0x00, 0x00, - 0xFC, 0x00, 0x00, - 0xF8, 0x00, 0x00, - 0xFC, 0x00, 0x00, - 0xDE, 0x00, 0x00, - 0x8F, 0x00, 0x00, - 0x07, 0x80, 0x00, - 0x03, 0xC0, 0x00, - 0x01, 0xE0, 0x00, - 0x00, 0xF0, 0x00, - 0x00, 0x78, 0x00, - 0x00, 0x38, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 -}; #endif @@ -159,25 +126,6 @@ int main (void) cursor (0); clrscr (); - /* The pointer should be created before the driver is installed, - ** in case a lightpen driver needs it during calibration. - */ - -#if defined(__C64__) || defined(__C128__) || defined(__CBM510__) - /* Copy the sprite data */ - memcpy ((void*) SPRITE0_DATA, MouseSprite, sizeof (MouseSprite)); - - /* Set the VIC-II sprite pointer. */ - *SPRITE0_PTR = ((unsigned) SPRITE0_DATA & 0x3FFF) / sizeof SPRITE0_DATA; - - /* Set the color of sprite 0 */ -# ifdef __CBM510__ - pokebsys ((unsigned) &VIC.spr0_color, COLOR_BLACK); -# else - VIC.spr0_color = COLOR_BLACK; -# endif -#endif - /* If a lightpen driver is installed, then it can get a calibration value ** from this file (if it exists). Or, the user can adjust the pen; and, ** the value will be put into this file, for the next time. diff --git a/samples/sieve.c b/samples/sieve.c index 9f110ec98..8d0619888 100644 --- a/samples/sieve.c +++ b/samples/sieve.c @@ -110,7 +110,7 @@ int main (void) J = 0; } } - if (kbhit() && ReadUpperKey == 'Q') { + if (kbhit() && ReadUpperKey () == 'Q') { break; } } diff --git a/src/ar65/exports.c b/src/ar65/exports.c index af176d019..b3bb4cebe 100644 --- a/src/ar65/exports.c +++ b/src/ar65/exports.c @@ -113,9 +113,9 @@ void ExpInsert (const char* Name, const ObjData* Module) while (1) { if (strcmp (L->Name, Name) == 0) { /* Duplicate entry */ - Warning ("External symbol `%s' in module `%s', library `%s' " + Warning ("External symbol `%s' in module `%s', library `%s', " "is duplicated in module `%s'", - Name, L->Name, LibName, Module->Name); + Name, L->Module->Name, LibName, Module->Name); } if (L->Next == 0) { break; diff --git a/src/ca65/expr.c b/src/ca65/expr.c index e4d6f7363..ff4232c00 100644 --- a/src/ca65/expr.c +++ b/src/ca65/expr.c @@ -62,6 +62,7 @@ #include "symtab.h" #include "toklist.h" #include "ulabel.h" +#include "macro.h" @@ -417,6 +418,26 @@ static ExprNode* FuncDefined (void) +static ExprNode* FuncDefinedMacro (void) +/* Handle the .DEFINEDMACRO builtin function */ +{ + Macro* Mac = 0; + + /* Check if the identifier is a macro */ + + if (CurTok.Tok == TOK_IDENT) { + Mac = FindMacro (&CurTok.SVal); + } else { + Error ("Identifier expected."); + } + /* Skip the name */ + NextTok (); + + return GenLiteralExpr (Mac != 0); +} + + + ExprNode* FuncHiByte (void) /* Handle the .HIBYTE builtin function */ { @@ -433,6 +454,36 @@ static ExprNode* FuncHiWord (void) +static ExprNode* FuncIsMnemonic (void) +/* Handle the .ISMNEMONIC, .ISMNEM builtin function */ +{ + int Instr = -1; + + /* Check for a macro or an instruction depending on UbiquitousIdents */ + + if (CurTok.Tok == TOK_IDENT) { + if (UbiquitousIdents) { + /* Macros CAN be instructions, so check for them first */ + if (FindMacro (&CurTok.SVal) == 0) { + Instr = FindInstruction (&CurTok.SVal); + } + } + else { + /* Macros and symbols may NOT use the names of instructions, so just check for the instruction */ + Instr = FindInstruction (&CurTok.SVal); + } + } + else { + Error ("Identifier expected."); + } + /* Skip the name */ + NextTok (); + + return GenLiteralExpr (Instr > 0); +} + + + ExprNode* FuncLoByte (void) /* Handle the .LOBYTE builtin function */ { @@ -629,6 +680,85 @@ static ExprNode* FuncReferenced (void) +static ExprNode* FuncAddrSize (void) +/* Handle the .ADDRSIZE function */ +{ + StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; + StrBuf Name = STATIC_STRBUF_INITIALIZER; + SymEntry* Sym; + int AddrSize; + int NoScope; + + + /* Assume we don't know the size */ + AddrSize = 0; + + /* Check for a cheap local which needs special handling */ + if (CurTok.Tok == TOK_LOCAL_IDENT) { + + /* Cheap local symbol */ + Sym = SymFindLocal (SymLast, &CurTok.SVal, SYM_FIND_EXISTING); + if (Sym == 0) { + Error ("Unknown symbol or scope: `%m%p'", &CurTok.SVal); + } else { + AddrSize = Sym->AddrSize; + } + + /* Remember and skip SVal, terminate ScopeName so it is empty */ + SB_Copy (&Name, &CurTok.SVal); + NextTok (); + SB_Terminate (&ScopeName); + + } else { + + /* Parse the scope and the name */ + SymTable* ParentScope = ParseScopedIdent (&Name, &ScopeName); + + /* Check if the parent scope is valid */ + if (ParentScope == 0) { + /* No such scope */ + SB_Done (&ScopeName); + SB_Done (&Name); + return GenLiteral0 (); + } + + /* If ScopeName is empty, no explicit scope was specified. We have to + ** search upper scope levels in this case. + */ + NoScope = SB_IsEmpty (&ScopeName); + + /* If we did find a scope with the name, read the symbol defining the + ** size, otherwise search for a symbol entry with the name and scope. + */ + if (NoScope) { + Sym = SymFindAny (ParentScope, &Name); + } else { + Sym = SymFind (ParentScope, &Name, SYM_FIND_EXISTING); + } + /* If we found the symbol retrieve the size, otherwise complain */ + if (Sym) { + AddrSize = Sym->AddrSize; + } else { + Error ("Unknown symbol or scope: `%m%p%m%p'", &ScopeName, &Name); + } + + } + + if (AddrSize == 0) { + Warning (1, "Unknown address size: `%m%p%m%p'", &ScopeName, &Name); + } + + /* Free the string buffers */ + SB_Done (&ScopeName); + SB_Done (&Name); + + /* Return the size. */ + + return GenLiteralExpr (AddrSize); +} + + + static ExprNode* FuncSizeOf (void) /* Handle the .SIZEOF function */ { @@ -965,6 +1095,19 @@ static ExprNode* Factor (void) N = Function (FuncBankByte); break; + case TOK_ADDRSIZE: + N = Function (FuncAddrSize); + break; + + case TOK_ASIZE: + if (GetCPU () != CPU_65816) { + N = GenLiteralExpr (8); + } else { + N = GenLiteralExpr (ExtBytes[AM65I_IMM_ACCU] * 8); + } + NextTok (); + break; + case TOK_BLANK: N = Function (FuncBlank); break; @@ -982,6 +1125,10 @@ static ExprNode* Factor (void) N = Function (FuncDefined); break; + case TOK_DEFINEDMACRO: + N = Function (FuncDefinedMacro); + break; + case TOK_HIBYTE: N = Function (FuncHiByte); break; @@ -990,6 +1137,19 @@ static ExprNode* Factor (void) N = Function (FuncHiWord); break; + case TOK_ISMNEMONIC: + N = Function (FuncIsMnemonic); + break; + + case TOK_ISIZE: + if (GetCPU () != CPU_65816) { + N = GenLiteralExpr (8); + } else { + N = GenLiteralExpr (ExtBytes[AM65I_IMM_INDEX] * 8); + } + NextTok (); + break; + case TOK_LOBYTE: N = Function (FuncLoByte); break; diff --git a/src/ca65/feature.c b/src/ca65/feature.c index c398d2b37..3462d5501 100644 --- a/src/ca65/feature.c +++ b/src/ca65/feature.c @@ -63,6 +63,7 @@ static const char* FeatureKeys[FEAT_COUNT] = { "c_comments", "force_range", "underline_in_numbers", + "addrsize", }; @@ -119,6 +120,7 @@ feature_t SetFeature (const StrBuf* Key) case FEAT_C_COMMENTS: CComments = 1; break; case FEAT_FORCE_RANGE: ForceRange = 1; break; case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break; + case FEAT_ADDRSIZE: AddrSize = 1; break; default: /* Keep gcc silent */ break; } diff --git a/src/ca65/feature.h b/src/ca65/feature.h index 9682ad9b9..3a520a54a 100644 --- a/src/ca65/feature.h +++ b/src/ca65/feature.h @@ -65,6 +65,7 @@ typedef enum { FEAT_C_COMMENTS, FEAT_FORCE_RANGE, FEAT_UNDERLINE_IN_NUMBERS, + FEAT_ADDRSIZE, /* Special value: Number of features available */ FEAT_COUNT diff --git a/src/ca65/filetab.c b/src/ca65/filetab.c index fbe163f51..ce4b15c03 100644 --- a/src/ca65/filetab.c +++ b/src/ca65/filetab.c @@ -262,6 +262,21 @@ void WriteFiles (void) +static void WriteEscaped (FILE* F, const char* Name) +/* Write a file name to a dependency file escaping spaces */ +{ + while (*Name) { + if (*Name == ' ') { + /* Escape spaces */ + fputc ('\\', F); + } + fputc (*Name, F); + ++Name; + } +} + + + static void WriteDep (FILE* F, FileType Types) /* Helper function. Writes all file names that match Types to the output */ { @@ -285,9 +300,9 @@ static void WriteDep (FILE* F, FileType Types) fputc (' ', F); } - /* Print the dependency */ + /* Print the dependency escaping spaces */ Filename = GetStrBuf (E->Name); - fprintf (F, "%*s", SB_GetLen (Filename), SB_GetConstBuf (Filename)); + WriteEscaped (F, SB_GetConstBuf (Filename)); } } @@ -305,7 +320,8 @@ static void CreateDepFile (const char* Name, FileType Types) } /* Print the output file followed by a tab char */ - fprintf (F, "%s:\t", OutFile); + WriteEscaped (F, OutFile); + fputs (":\t", F); /* Write out the dependencies for the output file */ WriteDep (F, Types); diff --git a/src/ca65/global.c b/src/ca65/global.c index b3d6d6c6e..e77b9201c 100644 --- a/src/ca65/global.c +++ b/src/ca65/global.c @@ -82,3 +82,5 @@ unsigned char OrgPerSeg = 0; /* Make .org local to current seg */ unsigned char CComments = 0; /* Allow C like comments */ unsigned char ForceRange = 0; /* Force values into expected range */ unsigned char UnderlineInNumbers = 0; /* Allow underlines in numbers */ +unsigned char AddrSize = 0; /* Allow .ADDRSIZE function */ + diff --git a/src/ca65/global.h b/src/ca65/global.h index 378a776e6..fb254f835 100644 --- a/src/ca65/global.h +++ b/src/ca65/global.h @@ -84,6 +84,8 @@ extern unsigned char OrgPerSeg; /* Make .org local to current seg */ extern unsigned char CComments; /* Allow C like comments */ extern unsigned char ForceRange; /* Force values into expected range */ extern unsigned char UnderlineInNumbers; /* Allow underlines in numbers */ +extern unsigned char AddrSize; /* Allow .ADDRSIZE function */ + diff --git a/src/ca65/instr.c b/src/ca65/instr.c index 6acf8c94f..500db1985 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -713,9 +713,9 @@ static const struct { { "ROR", 0x000006F, 0x62, 1, PutAll }, { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTS", 0x0000001, 0x60, 0, PutAll }, - { "SBC", 0x080A66C, 0xe0, 0, PutAll }, { "SAX", 0x0000001, 0x22, 0, PutAll }, { "SAY", 0x0000001, 0x42, 0, PutAll }, + { "SBC", 0x080A66C, 0xe0, 0, PutAll }, { "SEC", 0x0000001, 0x38, 0, PutAll }, { "SED", 0x0000001, 0xf8, 0, PutAll }, { "SEI", 0x0000001, 0x78, 0, PutAll }, diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 634f2107e..1f6812ce0 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -147,7 +147,7 @@ static int DoMacAbort = 0; /* Counter to create local names for symbols */ static unsigned LocalName = 0; -/* Define style macros disabled if != 0 */ +/* Define-style macros disabled if != 0 */ static unsigned DisableDefines = 0; @@ -422,8 +422,8 @@ void MacDef (unsigned Style) EnterRawTokenMode (); NextTok (); - /* If we have a DEFINE style macro, we may have parameters in braces, - ** otherwise we may have parameters without braces. + /* If we have a DEFINE-style macro, we may have parameters in parentheses; + ** otherwise, we may have parameters without parentheses. */ if (Style == MAC_STYLE_CLASSIC) { HaveParams = 1; @@ -475,7 +475,7 @@ void MacDef (unsigned Style) } } - /* For class macros, we expect a separator token, for define style macros, + /* For classic macros, we expect a separator token, for define-style macros, ** we expect the closing paren. */ if (Style == MAC_STYLE_CLASSIC) { @@ -485,9 +485,9 @@ void MacDef (unsigned Style) } /* Preparse the macro body. We will read the tokens until we reach end of - ** file, or a .endmacro (or end of line for DEFINE style macros) and store - ** them into an token list internal to the macro. For classic macros, there - ** the .LOCAL command is detected and removed at this time. + ** file, or a .endmacro (or end of line for DEFINE-style macros) and store + ** them into a token list internal to the macro. For classic macros, + ** the .LOCAL command is detected and removed, at this time. */ while (1) { @@ -752,11 +752,11 @@ ExpandParam: FreeTokNode (Mac->Final); Mac->Final = 0; - /* Problem: When a .define style macro is expanded within the call + /* Problem: When a .define-style macro is expanded within the call ** of a classic one, the latter may be terminated and removed while - ** the expansion of the .define style macro is still active. Because + ** the expansion of the .define-style macro is still active. Because ** line info slots are "stacked", this runs into a CHECK FAILED. For - ** now, we will fix that by removing the .define style macro expansion + ** now, we will fix that by removing the .define-style macro expansion ** immediately, once the final token is placed. The better solution ** would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot ** to be called in FIFO order, but this is a bigger change. @@ -785,72 +785,74 @@ MacEnd: static void StartExpClassic (MacExp* E) /* Start expanding a classic macro */ { - token_t Term; + token_t Term; /* Skip the macro name */ NextTok (); - /* Read the actual parameters */ - while (!TokIsSep (CurTok.Tok)) { + /* Does this invocation have any arguments? */ + if (!TokIsSep (CurTok.Tok)) { - TokNode* Last; + /* Read the actual parameters */ + while (1) { + TokNode* Last; - /* Check for maximum parameter count */ - if (E->ParamCount >= E->M->ParamCount) { - ErrorSkip ("Too many macro parameters"); - break; - } - - /* The macro may optionally be enclosed in curly braces */ - Term = GetTokListTerm (TOK_COMMA); - - /* Read tokens for one parameter, accept empty params */ - Last = 0; - while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) { - - TokNode* T; - - /* Check for end of file */ - if (CurTok.Tok == TOK_EOF) { - Error ("Unexpected end of file"); - FreeMacExp (E); - return; - } - - /* Get the next token in a node */ - T = NewTokNode (); - - /* Insert it into the list */ - if (Last == 0) { - E->Params [E->ParamCount] = T; - } else { - Last->Next = T; - } - Last = T; - - /* And skip it... */ - NextTok (); - } - - /* One parameter more */ - ++E->ParamCount; - - /* If the macro argument was enclosed in curly braces, end-of-line - ** is an error. Skip the closing curly brace. - */ - if (Term == TOK_RCURLY) { - if (CurTok.Tok == TOK_SEP) { - Error ("End of line encountered within macro argument"); + /* Check for maximum parameter count */ + if (E->ParamCount >= E->M->ParamCount) { + ErrorSkip ("Too many macro parameters"); break; } - NextTok (); - } - /* Check for a comma */ - if (CurTok.Tok == TOK_COMMA) { - NextTok (); - } else { - break; + /* The macro argument optionally may be enclosed in curly braces */ + Term = GetTokListTerm (TOK_COMMA); + + /* Read tokens for one parameter, accept empty params */ + Last = 0; + while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) { + TokNode* T; + + /* Check for end of file */ + if (CurTok.Tok == TOK_EOF) { + Error ("Unexpected end of file"); + FreeMacExp (E); + return; + } + + /* Get the next token in a node */ + T = NewTokNode (); + + /* Insert it into the list */ + if (Last == 0) { + E->Params [E->ParamCount] = T; + } else { + Last->Next = T; + } + Last = T; + + /* And skip it... */ + NextTok (); + } + + /* One parameter more */ + ++E->ParamCount; + + /* If the macro argument was enclosed in curly braces, end-of-line + ** is an error. Skip the closing curly brace. + */ + if (Term == TOK_RCURLY) { + if (CurTok.Tok == TOK_SEP) { + Error ("End of line encountered within macro argument"); + break; + } + NextTok (); + } + + /* Check for a comma */ + if (CurTok.Tok == TOK_COMMA) { + NextTok (); + } else { + break; + } } } @@ -864,9 +866,9 @@ static void StartExpClassic (MacExp* E) static void StartExpDefine (MacExp* E) -/* Start expanding a DEFINE style macro */ +/* Start expanding a DEFINE-style macro */ { - /* A define style macro must be called with as many actual parameters + /* A define-style macro must be called with as many actual parameters ** as there are formal ones. Get the parameter count. */ unsigned Count = E->M->ParamCount; @@ -876,10 +878,9 @@ static void StartExpDefine (MacExp* E) /* Read the actual parameters */ while (Count--) { + TokNode* Last; - TokNode* Last; - - /* The macro may optionally be enclosed in curly braces */ + /* The macro argument optionally may be enclosed in curly braces */ token_t Term = GetTokListTerm (TOK_COMMA); /* Check if there is really a parameter */ @@ -892,7 +893,6 @@ static void StartExpDefine (MacExp* E) /* Read tokens for one parameter */ Last = 0; do { - TokNode* T; /* Get the next token in a node */ @@ -936,7 +936,7 @@ static void StartExpDefine (MacExp* E) } /* Macro expansion will overwrite the current token. This is a problem - ** for define style macros since these are called from the scanner level. + ** for define-style macros since these are called from the scanner level. ** To avoid it, remember the current token and re-insert it, once macro ** expansion is done. */ @@ -1007,8 +1007,8 @@ Macro* FindMacro (const StrBuf* Name) Macro* FindDefine (const StrBuf* Name) -/* Try to find the define style macro with the given name and return it. If no -** such macro was found, return NULL. +/* Try to find the define-style macro with the given name; and, return it. +** If no such macro was found, return NULL. */ { Macro* M; @@ -1034,7 +1034,7 @@ int InMacExpansion (void) void DisableDefineStyleMacros (void) -/* Disable define style macros until EnableDefineStyleMacros is called */ +/* Disable define-style macros until EnableDefineStyleMacros() is called */ { ++DisableDefines; } @@ -1042,8 +1042,8 @@ void DisableDefineStyleMacros (void) void EnableDefineStyleMacros (void) -/* Re-enable define style macros previously disabled with -** DisableDefineStyleMacros. +/* Re-enable define-style macros previously disabled with +** DisableDefineStyleMacros(). */ { PRECONDITION (DisableDefines > 0); diff --git a/src/ca65/main.c b/src/ca65/main.c index 3f31a2b88..d81a87577 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -303,6 +303,14 @@ static void SetSys (const char* Sys) NewSymbol ("__SIM65C02__", 1); break; + case TGT_OSIC1P: + NewSymbol ("__OSIC1P__", 1); + break; + + case TGT_PCENGINE: + NewSymbol ("__PCE__", 1); + break; + default: AbEnd ("Invalid target name: `%s'", Sys); diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 0b066c7bd..4db780318 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1964,8 +1964,10 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoA16 }, { ccNone, DoA8 }, { ccNone, DoAddr }, /* .ADDR */ + { ccNone, DoUnexpected }, /* .ADDRSIZE */ { ccNone, DoAlign }, { ccNone, DoASCIIZ }, + { ccNone, DoUnexpected }, /* .ASIZE */ { ccNone, DoAssert }, { ccNone, DoAutoImport }, { ccNone, DoUnexpected }, /* .BANK */ @@ -1988,6 +1990,7 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoDebugInfo }, { ccNone, DoDefine }, { ccNone, DoUnexpected }, /* .DEFINED */ + { ccNone, DoUnexpected }, /* .DEFINEDMACRO */ { ccNone, DoDelMac }, { ccNone, DoDestructor }, { ccNone, DoDWord }, @@ -2039,6 +2042,8 @@ static CtrlDesc CtrlCmdTab [] = { { ccNone, DoIncBin }, { ccNone, DoInclude }, { ccNone, DoInterruptor }, + { ccNone, DoUnexpected }, /* .ISIZE */ + { ccNone, DoUnexpected }, /* .ISMNEMONIC */ { ccNone, DoInvalid }, /* .LEFT */ { ccNone, DoLineCont }, { ccNone, DoList }, diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 890e1c7a3..799321066 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -132,162 +132,168 @@ struct DotKeyword { const char* Key; /* MUST be first field */ token_t Tok; } DotKeywords [] = { - { ".A16", TOK_A16 }, - { ".A8", TOK_A8 }, - { ".ADDR", TOK_ADDR }, - { ".ALIGN", TOK_ALIGN }, - { ".AND", TOK_BOOLAND }, - { ".ASCIIZ", TOK_ASCIIZ }, - { ".ASSERT", TOK_ASSERT }, - { ".AUTOIMPORT", TOK_AUTOIMPORT }, - { ".BANK", TOK_BANK }, - { ".BANKBYTE", TOK_BANKBYTE }, - { ".BANKBYTES", TOK_BANKBYTES }, - { ".BITAND", TOK_AND }, - { ".BITNOT", TOK_NOT }, - { ".BITOR", TOK_OR }, - { ".BITXOR", TOK_XOR }, - { ".BLANK", TOK_BLANK }, - { ".BSS", TOK_BSS }, - { ".BYT", TOK_BYTE }, - { ".BYTE", TOK_BYTE }, - { ".CASE", TOK_CASE }, - { ".CHARMAP", TOK_CHARMAP }, - { ".CODE", TOK_CODE }, - { ".CONCAT", TOK_CONCAT }, - { ".CONDES", TOK_CONDES }, - { ".CONST", TOK_CONST }, - { ".CONSTRUCTOR", TOK_CONSTRUCTOR }, - { ".CPU", TOK_CPU }, - { ".DATA", TOK_DATA }, - { ".DBG", TOK_DBG }, - { ".DBYT", TOK_DBYT }, - { ".DEBUGINFO", TOK_DEBUGINFO }, - { ".DEF", TOK_DEFINED }, - { ".DEFINE", TOK_DEFINE }, - { ".DEFINED", TOK_DEFINED }, - { ".DELMAC", TOK_DELMAC }, - { ".DELMACRO", TOK_DELMAC }, - { ".DESTRUCTOR", TOK_DESTRUCTOR }, - { ".DWORD", TOK_DWORD }, - { ".ELSE", TOK_ELSE }, - { ".ELSEIF", TOK_ELSEIF }, - { ".END", TOK_END }, - { ".ENDENUM", TOK_ENDENUM }, - { ".ENDIF", TOK_ENDIF }, - { ".ENDMAC", TOK_ENDMACRO }, - { ".ENDMACRO", TOK_ENDMACRO }, - { ".ENDPROC", TOK_ENDPROC }, - { ".ENDREP", TOK_ENDREP }, - { ".ENDREPEAT", TOK_ENDREP }, - { ".ENDSCOPE", TOK_ENDSCOPE }, - { ".ENDSTRUCT", TOK_ENDSTRUCT }, - { ".ENDUNION", TOK_ENDUNION }, - { ".ENUM", TOK_ENUM }, - { ".ERROR", TOK_ERROR }, - { ".EXITMAC", TOK_EXITMACRO }, - { ".EXITMACRO", TOK_EXITMACRO }, - { ".EXPORT", TOK_EXPORT }, - { ".EXPORTZP", TOK_EXPORTZP }, - { ".FARADDR", TOK_FARADDR }, - { ".FATAL", TOK_FATAL }, - { ".FEATURE", TOK_FEATURE }, - { ".FILEOPT", TOK_FILEOPT }, - { ".FOPT", TOK_FILEOPT }, - { ".FORCEIMPORT", TOK_FORCEIMPORT }, - { ".FORCEWORD", TOK_FORCEWORD }, - { ".GLOBAL", TOK_GLOBAL }, - { ".GLOBALZP", TOK_GLOBALZP }, - { ".HIBYTE", TOK_HIBYTE }, - { ".HIBYTES", TOK_HIBYTES }, - { ".HIWORD", TOK_HIWORD }, - { ".I16", TOK_I16 }, - { ".I8", TOK_I8 }, - { ".IDENT", TOK_MAKEIDENT }, - { ".IF", TOK_IF }, - { ".IFBLANK", TOK_IFBLANK }, - { ".IFCONST", TOK_IFCONST }, - { ".IFDEF", TOK_IFDEF }, - { ".IFNBLANK", TOK_IFNBLANK }, - { ".IFNCONST", TOK_IFNCONST }, - { ".IFNDEF", TOK_IFNDEF }, - { ".IFNREF", TOK_IFNREF }, - { ".IFP02", TOK_IFP02 }, - { ".IFP816", TOK_IFP816 }, - { ".IFPC02", TOK_IFPC02 }, - { ".IFPSC02", TOK_IFPSC02 }, - { ".IFREF", TOK_IFREF }, - { ".IMPORT", TOK_IMPORT }, - { ".IMPORTZP", TOK_IMPORTZP }, - { ".INCBIN", TOK_INCBIN }, - { ".INCLUDE", TOK_INCLUDE }, - { ".INTERRUPTOR", TOK_INTERRUPTOR }, - { ".LEFT", TOK_LEFT }, - { ".LINECONT", TOK_LINECONT }, - { ".LIST", TOK_LIST }, - { ".LISTBYTES", TOK_LISTBYTES }, - { ".LOBYTE", TOK_LOBYTE }, - { ".LOBYTES", TOK_LOBYTES }, - { ".LOCAL", TOK_LOCAL }, - { ".LOCALCHAR", TOK_LOCALCHAR }, - { ".LOWORD", TOK_LOWORD }, - { ".MAC", TOK_MACRO }, - { ".MACPACK", TOK_MACPACK }, - { ".MACRO", TOK_MACRO }, - { ".MATCH", TOK_MATCH }, - { ".MAX", TOK_MAX }, - { ".MID", TOK_MID }, - { ".MIN", TOK_MIN }, - { ".MOD", TOK_MOD }, - { ".NOT", TOK_BOOLNOT }, - { ".NULL", TOK_NULL }, - { ".OR", TOK_BOOLOR }, - { ".ORG", TOK_ORG }, - { ".OUT", TOK_OUT }, - { ".P02", TOK_P02 }, - { ".P816", TOK_P816 }, - { ".PAGELEN", TOK_PAGELENGTH }, - { ".PAGELENGTH", TOK_PAGELENGTH }, - { ".PARAMCOUNT", TOK_PARAMCOUNT }, - { ".PC02", TOK_PC02 }, - { ".POPCPU", TOK_POPCPU }, - { ".POPSEG", TOK_POPSEG }, - { ".PROC", TOK_PROC }, - { ".PSC02", TOK_PSC02 }, - { ".PUSHCPU", TOK_PUSHCPU }, - { ".PUSHSEG", TOK_PUSHSEG }, - { ".REF", TOK_REFERENCED }, - { ".REFERENCED", TOK_REFERENCED }, - { ".RELOC", TOK_RELOC }, - { ".REPEAT", TOK_REPEAT }, - { ".RES", TOK_RES }, - { ".RIGHT", TOK_RIGHT }, - { ".RODATA", TOK_RODATA }, - { ".SCOPE", TOK_SCOPE }, - { ".SEGMENT", TOK_SEGMENT }, - { ".SET", TOK_SET }, - { ".SETCPU", TOK_SETCPU }, - { ".SHL", TOK_SHL }, - { ".SHR", TOK_SHR }, - { ".SIZEOF", TOK_SIZEOF }, - { ".SMART", TOK_SMART }, - { ".SPRINTF", TOK_SPRINTF }, - { ".STRAT", TOK_STRAT }, - { ".STRING", TOK_STRING }, - { ".STRLEN", TOK_STRLEN }, - { ".STRUCT", TOK_STRUCT }, - { ".TAG", TOK_TAG }, - { ".TCOUNT", TOK_TCOUNT }, - { ".TIME", TOK_TIME }, - { ".UNDEF", TOK_UNDEF }, - { ".UNDEFINE", TOK_UNDEF }, - { ".UNION", TOK_UNION }, - { ".VERSION", TOK_VERSION }, - { ".WARNING", TOK_WARNING }, - { ".WORD", TOK_WORD }, - { ".XMATCH", TOK_XMATCH }, - { ".XOR", TOK_BOOLXOR }, - { ".ZEROPAGE", TOK_ZEROPAGE }, + { ".A16", TOK_A16 }, + { ".A8", TOK_A8 }, + { ".ADDR", TOK_ADDR }, + { ".ADDRSIZE", TOK_ADDRSIZE }, + { ".ALIGN", TOK_ALIGN }, + { ".AND", TOK_BOOLAND }, + { ".ASCIIZ", TOK_ASCIIZ }, + { ".ASIZE", TOK_ASIZE }, + { ".ASSERT", TOK_ASSERT }, + { ".AUTOIMPORT", TOK_AUTOIMPORT }, + { ".BANK", TOK_BANK }, + { ".BANKBYTE", TOK_BANKBYTE }, + { ".BANKBYTES", TOK_BANKBYTES }, + { ".BITAND", TOK_AND }, + { ".BITNOT", TOK_NOT }, + { ".BITOR", TOK_OR }, + { ".BITXOR", TOK_XOR }, + { ".BLANK", TOK_BLANK }, + { ".BSS", TOK_BSS }, + { ".BYT", TOK_BYTE }, + { ".BYTE", TOK_BYTE }, + { ".CASE", TOK_CASE }, + { ".CHARMAP", TOK_CHARMAP }, + { ".CODE", TOK_CODE }, + { ".CONCAT", TOK_CONCAT }, + { ".CONDES", TOK_CONDES }, + { ".CONST", TOK_CONST }, + { ".CONSTRUCTOR", TOK_CONSTRUCTOR }, + { ".CPU", TOK_CPU }, + { ".DATA", TOK_DATA }, + { ".DBG", TOK_DBG }, + { ".DBYT", TOK_DBYT }, + { ".DEBUGINFO", TOK_DEBUGINFO }, + { ".DEF", TOK_DEFINED }, + { ".DEFINE", TOK_DEFINE }, + { ".DEFINED", TOK_DEFINED }, + { ".DEFINEDMACRO", TOK_DEFINEDMACRO }, + { ".DELMAC", TOK_DELMAC }, + { ".DELMACRO", TOK_DELMAC }, + { ".DESTRUCTOR", TOK_DESTRUCTOR }, + { ".DWORD", TOK_DWORD }, + { ".ELSE", TOK_ELSE }, + { ".ELSEIF", TOK_ELSEIF }, + { ".END", TOK_END }, + { ".ENDENUM", TOK_ENDENUM }, + { ".ENDIF", TOK_ENDIF }, + { ".ENDMAC", TOK_ENDMACRO }, + { ".ENDMACRO", TOK_ENDMACRO }, + { ".ENDPROC", TOK_ENDPROC }, + { ".ENDREP", TOK_ENDREP }, + { ".ENDREPEAT", TOK_ENDREP }, + { ".ENDSCOPE", TOK_ENDSCOPE }, + { ".ENDSTRUCT", TOK_ENDSTRUCT }, + { ".ENDUNION", TOK_ENDUNION }, + { ".ENUM", TOK_ENUM }, + { ".ERROR", TOK_ERROR }, + { ".EXITMAC", TOK_EXITMACRO }, + { ".EXITMACRO", TOK_EXITMACRO }, + { ".EXPORT", TOK_EXPORT }, + { ".EXPORTZP", TOK_EXPORTZP }, + { ".FARADDR", TOK_FARADDR }, + { ".FATAL", TOK_FATAL }, + { ".FEATURE", TOK_FEATURE }, + { ".FILEOPT", TOK_FILEOPT }, + { ".FOPT", TOK_FILEOPT }, + { ".FORCEIMPORT", TOK_FORCEIMPORT }, + { ".FORCEWORD", TOK_FORCEWORD }, + { ".GLOBAL", TOK_GLOBAL }, + { ".GLOBALZP", TOK_GLOBALZP }, + { ".HIBYTE", TOK_HIBYTE }, + { ".HIBYTES", TOK_HIBYTES }, + { ".HIWORD", TOK_HIWORD }, + { ".I16", TOK_I16 }, + { ".I8", TOK_I8 }, + { ".IDENT", TOK_MAKEIDENT }, + { ".IF", TOK_IF }, + { ".IFBLANK", TOK_IFBLANK }, + { ".IFCONST", TOK_IFCONST }, + { ".IFDEF", TOK_IFDEF }, + { ".IFNBLANK", TOK_IFNBLANK }, + { ".IFNCONST", TOK_IFNCONST }, + { ".IFNDEF", TOK_IFNDEF }, + { ".IFNREF", TOK_IFNREF }, + { ".IFP02", TOK_IFP02 }, + { ".IFP816", TOK_IFP816 }, + { ".IFPC02", TOK_IFPC02 }, + { ".IFPSC02", TOK_IFPSC02 }, + { ".IFREF", TOK_IFREF }, + { ".IMPORT", TOK_IMPORT }, + { ".IMPORTZP", TOK_IMPORTZP }, + { ".INCBIN", TOK_INCBIN }, + { ".INCLUDE", TOK_INCLUDE }, + { ".INTERRUPTOR", TOK_INTERRUPTOR }, + { ".ISIZE", TOK_ISIZE }, + { ".ISMNEM", TOK_ISMNEMONIC }, + { ".ISMNEMONIC", TOK_ISMNEMONIC }, + { ".LEFT", TOK_LEFT }, + { ".LINECONT", TOK_LINECONT }, + { ".LIST", TOK_LIST }, + { ".LISTBYTES", TOK_LISTBYTES }, + { ".LOBYTE", TOK_LOBYTE }, + { ".LOBYTES", TOK_LOBYTES }, + { ".LOCAL", TOK_LOCAL }, + { ".LOCALCHAR", TOK_LOCALCHAR }, + { ".LOWORD", TOK_LOWORD }, + { ".MAC", TOK_MACRO }, + { ".MACPACK", TOK_MACPACK }, + { ".MACRO", TOK_MACRO }, + { ".MATCH", TOK_MATCH }, + { ".MAX", TOK_MAX }, + { ".MID", TOK_MID }, + { ".MIN", TOK_MIN }, + { ".MOD", TOK_MOD }, + { ".NOT", TOK_BOOLNOT }, + { ".NULL", TOK_NULL }, + { ".OR", TOK_BOOLOR }, + { ".ORG", TOK_ORG }, + { ".OUT", TOK_OUT }, + { ".P02", TOK_P02 }, + { ".P816", TOK_P816 }, + { ".PAGELEN", TOK_PAGELENGTH }, + { ".PAGELENGTH", TOK_PAGELENGTH }, + { ".PARAMCOUNT", TOK_PARAMCOUNT }, + { ".PC02", TOK_PC02 }, + { ".POPCPU", TOK_POPCPU }, + { ".POPSEG", TOK_POPSEG }, + { ".PROC", TOK_PROC }, + { ".PSC02", TOK_PSC02 }, + { ".PUSHCPU", TOK_PUSHCPU }, + { ".PUSHSEG", TOK_PUSHSEG }, + { ".REF", TOK_REFERENCED }, + { ".REFERENCED", TOK_REFERENCED }, + { ".RELOC", TOK_RELOC }, + { ".REPEAT", TOK_REPEAT }, + { ".RES", TOK_RES }, + { ".RIGHT", TOK_RIGHT }, + { ".RODATA", TOK_RODATA }, + { ".SCOPE", TOK_SCOPE }, + { ".SEGMENT", TOK_SEGMENT }, + { ".SET", TOK_SET }, + { ".SETCPU", TOK_SETCPU }, + { ".SHL", TOK_SHL }, + { ".SHR", TOK_SHR }, + { ".SIZEOF", TOK_SIZEOF }, + { ".SMART", TOK_SMART }, + { ".SPRINTF", TOK_SPRINTF }, + { ".STRAT", TOK_STRAT }, + { ".STRING", TOK_STRING }, + { ".STRLEN", TOK_STRLEN }, + { ".STRUCT", TOK_STRUCT }, + { ".TAG", TOK_TAG }, + { ".TCOUNT", TOK_TCOUNT }, + { ".TIME", TOK_TIME }, + { ".UNDEF", TOK_UNDEF }, + { ".UNDEFINE", TOK_UNDEF }, + { ".UNION", TOK_UNION }, + { ".VERSION", TOK_VERSION }, + { ".WARNING", TOK_WARNING }, + { ".WORD", TOK_WORD }, + { ".XMATCH", TOK_XMATCH }, + { ".XOR", TOK_BOOLXOR }, + { ".ZEROPAGE", TOK_ZEROPAGE }, }; @@ -723,7 +729,24 @@ static token_t FindDotKeyword (void) R = bsearch (&K, DotKeywords, sizeof (DotKeywords) / sizeof (DotKeywords [0]), sizeof (DotKeywords [0]), CmpDotKeyword); if (R != 0) { + + /* By default, disable any somewhat experiemental DotKeyword. */ + + switch (R->Tok) { + + case TOK_ADDRSIZE: + /* Disallow .ADDRSIZE function by default */ + if (AddrSize == 0) { + return TOK_NONE; + } + break; + + default: + break; + } + return R->Tok; + } else { return TOK_NONE; } @@ -991,7 +1014,7 @@ Again: break; } DVal = DigitVal (Buf[I]); - if (DVal > Base) { + if (DVal >= Base) { Error ("Invalid digits in number"); CurTok.IVal = 0; break; @@ -1397,11 +1420,14 @@ CharAgain: /* Line continuation? */ if (LineCont) { NextChar (); + /* Next char should be a LF, if not, will result in an error later */ if (C == '\n') { - /* Handle as white space */ + /* Ignore the '\n' */ NextChar (); - C = ' '; goto Again; + } else { + /* Make it clear what the problem is: */ + Error ("EOL expected."); } } break; diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index f1459dca0..06c537cf6 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -570,8 +570,8 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri } } - /* If the symbol was already declared as a condes, check if the new - ** priority value is the same as the old one. + /* If the symbol already was declared as a condes of this type, + ** check if the new priority value is the same as the old one. */ if (S->ConDesPrio[Type] != CD_PRIO_NONE) { if (S->ConDesPrio[Type] != Prio) { @@ -583,10 +583,8 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri /* Set the symbol data */ S->Flags |= (SF_EXPORT | SF_REFERENCED); - /* In case we have no line info for the definition, record it now */ - if (CollCount (&S->DefLines) == 0) { - GetFullLineInfo (&S->DefLines); - } + /* Remember the line info for this reference */ + CollAppend (&S->RefLines, GetAsmLineInfo ()); } diff --git a/src/ca65/symtab.c b/src/ca65/symtab.c index 7e21dd309..35d5a8066 100644 --- a/src/ca65/symtab.c +++ b/src/ca65/symtab.c @@ -696,10 +696,10 @@ void SymDump (FILE* F) while (S) { /* Ignore unused symbols */ - if ((S->Flags & SF_UNUSED) != 0) { + if ((S->Flags & SF_UNUSED) == 0) { fprintf (F, - "%m%-24p %s %s %s %s %s\n", - GetSymName (S), + "%-24s %s %s %s %s %s\n", + SB_GetConstBuf (GetSymName (S)), (S->Flags & SF_DEFINED)? "DEF" : "---", (S->Flags & SF_REFERENCED)? "REF" : "---", (S->Flags & SF_IMPORT)? "IMP" : "---", diff --git a/src/ca65/token.h b/src/ca65/token.h index 803b12785..bfc013a3d 100644 --- a/src/ca65/token.h +++ b/src/ca65/token.h @@ -123,8 +123,10 @@ typedef enum token_t { TOK_A16 = TOK_FIRSTPSEUDO, TOK_A8, TOK_ADDR, + TOK_ADDRSIZE, TOK_ALIGN, TOK_ASCIIZ, + TOK_ASIZE, TOK_ASSERT, TOK_AUTOIMPORT, TOK_BANK, @@ -147,6 +149,7 @@ typedef enum token_t { TOK_DEBUGINFO, TOK_DEFINE, TOK_DEFINED, + TOK_DEFINEDMACRO, TOK_DELMAC, TOK_DESTRUCTOR, TOK_DWORD, @@ -198,6 +201,8 @@ typedef enum token_t { TOK_INCBIN, TOK_INCLUDE, TOK_INTERRUPTOR, + TOK_ISIZE, + TOK_ISMNEMONIC, TOK_LEFT, TOK_LINECONT, TOK_LIST, diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index be80319e7..de51781a6 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2001-2012, Ullrich von Bassewitz */ +/* (C) 2001-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -46,6 +46,7 @@ #include "codeseg.h" #include "datatype.h" #include "error.h" +#include "global.h" #include "reginfo.h" #include "symtab.h" #include "codeinfo.h" @@ -386,33 +387,35 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) ** Search for it in the list of builtin functions. */ if (Name[0] == '_') { - /* Search in the symbol table, skip the leading underscore */ SymEntry* E = FindGlobalSym (Name+1); - /* Did we find it in the top level table? */ + /* Did we find it in the top-level table? */ if (E && IsTypeFunc (E->Type)) { - FuncDesc* D = E->V.F.Func; - /* A function may use the A or A/X registers if it is a fastcall - ** function. If it is not a fastcall function but a variadic one, - ** it will use the Y register (the parameter size is passed here). - ** In all other cases, no registers are used. However, we assume - ** that any function will destroy all registers. + /* A variadic function will use the Y register (the parameter list + ** size is passed there). A fastcall function will use the A or A/X + ** registers. In all other cases, no registers are used. However, + ** we assume that any function will destroy all registers. */ - if (IsQualFastcall (E->Type) && D->ParamCount > 0) { - /* Will use registers depending on the last param */ - unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type); - if (LastParamSize == 1) { - *Use = REG_A; - } else if (LastParamSize == 2) { - *Use = REG_AX; - } else { - *Use = REG_EAX; - } - } else if ((D->Flags & FD_VARIADIC) != 0) { + if ((D->Flags & FD_VARIADIC) != 0) { *Use = REG_Y; + } else if (D->ParamCount > 0 && + (AutoCDecl ? + IsQualFastcall (E->Type) : + !IsQualCDecl (E->Type))) { + /* Will use registers depending on the last param. */ + switch (CheckedSizeOf (D->LastParam->Type)) { + case 1u: + *Use = REG_A; + break; + case 2u: + *Use = REG_AX; + break; + default: + *Use = REG_EAX; + } } else { /* Will not use any registers */ *Use = REG_NONE; diff --git a/src/cc65/coptshift.c b/src/cc65/coptshift.c index a4b993073..92210ebb5 100644 --- a/src/cc65/coptshift.c +++ b/src/cc65/coptshift.c @@ -307,59 +307,87 @@ NextEntry: -unsigned OptShift2(CodeSeg* S) -/* A call to the asrax1 routines may get replaced by something simpler, if -** X is not used later: +unsigned OptShift2 (CodeSeg* S) +/* The sequence +** +** bpl L +** dex +** L: jsr asraxN +** +** might be replaced by N copies of ** ** cmp #$80 ** ror a +** +** if X is not used later (X is assumed to be zero on entry). +** If the sequence is followed immediately by another +** +** jsr asraxN +** +** then their shifts are combined. */ { unsigned Changes = 0; - unsigned I; + unsigned I = 0; /* Walk over the entries */ - I = 0; while (I < CS_GetEntryCount (S)) { - unsigned Shift; - unsigned Count; + unsigned Count, Count2; + unsigned K; + CodeEntry* L[4]; /* Get next entry */ - CodeEntry* E = CS_GetEntry (S, I); + L[0] = CS_GetEntry (S, I); /* Check for the sequence */ - if (E->OPC == OP65_JSR && - (Shift = GetShift (E->Arg)) != SHIFT_NONE && - SHIFT_TYPE (Shift) == SHIFT_TYPE_ASR && - (Count = SHIFT_COUNT (Shift)) > 0 && - Count * 100 <= S->CodeSizeFactor && - !RegXUsed (S, I+1)) { + if ((L[0]->OPC == OP65_BPL || L[0]->OPC == OP65_BCC) && + L[0]->JumpTo != 0 && + CS_GetEntries (S, L+1, I+1, 3) && + L[1]->OPC == OP65_DEX && + L[0]->JumpTo->Owner == L[2] && + !CS_RangeHasLabel (S, I, 2) && + L[2]->OPC == OP65_JSR && + SHIFT_TYPE (Shift = GetShift (L[2]->Arg)) == SHIFT_TYPE_ASR && + (Count = SHIFT_COUNT (Shift)) > 0) { - CodeEntry* X; - unsigned J = I+1; + if (L[3]->OPC == OP65_JSR && + SHIFT_TYPE (Shift = GetShift (L[3]->Arg)) == SHIFT_TYPE_ASR && + (Count2 = SHIFT_COUNT (Shift)) > 0) { - /* Generate the replacement sequence */ - while (Count--) { - /* cmp #$80 */ - X = NewCodeEntry (OP65_CMP, AM65_IMM, "$80", 0, E->LI); - CS_InsertEntry (S, X, J++); - - /* ror a */ - X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, E->LI); - CS_InsertEntry (S, X, J++); + /* Found a second jsr asraxN */ + Count += Count2; + K = 4; + } else { + K = 3; } + if (Count * 100 <= S->CodeSizeFactor && + !RegXUsed (S, I+K)) { - /* Delete the call to asrax */ - CS_DelEntry (S, I); + CodeEntry* X; + unsigned J = I+K; - /* Remember, we had changes */ - ++Changes; + /* Generate the replacement sequence */ + do { + /* cmp #$80 */ + X = NewCodeEntry (OP65_CMP, AM65_IMM, "$80", 0, L[2]->LI); + CS_InsertEntry (S, X, J++); + + /* ror a */ + X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI); + CS_InsertEntry (S, X, J++); + } while (--Count); + + /* Remove the bpl/dex/jsr */ + CS_DelEntries (S, I, K); + + /* Remember, we had changes */ + ++Changes; + } } /* Next entry */ ++I; - } /* Return the number of changes made */ @@ -412,7 +440,7 @@ unsigned OptShift3 (CodeSeg* S) (Shift = GetShift (L[2]->Arg)) != SHIFT_NONE && SHIFT_DIR (Shift) == SHIFT_DIR_RIGHT && (Count = SHIFT_COUNT (Shift)) > 0) { - + /* Add the replacement insn instead */ CodeEntry* X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, I+3); @@ -421,7 +449,7 @@ unsigned OptShift3 (CodeSeg* S) CS_InsertEntry (S, X, I+4); } - /* Remove the bcs/dex/jsr */ + /* Remove the bcc/inx/jsr */ CS_DelEntries (S, I, 3); /* Remember, we had changes */ diff --git a/src/cc65/coptshift.h b/src/cc65/coptshift.h index 0410652a1..e7f9cc359 100644 --- a/src/cc65/coptshift.h +++ b/src/cc65/coptshift.h @@ -60,12 +60,19 @@ unsigned OptShift1 (CodeSeg* S); ** L1: */ -unsigned OptShift2(CodeSeg* S); -/* A call to the asrax1 routines may get replaced by something simpler, if -** X is not used later: +unsigned OptShift2 (CodeSeg* S); +/* The sequence +** +** bpl L +** dex +** L: jsr asraxN +** +** might be replaced by N copies of ** ** cmp #$80 ** ror a +** +** if X is not used later (X is assumed to be zero on entry). */ unsigned OptShift3 (CodeSeg* S); diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 427d0bd13..cf6392bd3 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -766,12 +766,8 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer InsertEntry (D, X, D->IP++); /* Lhs load entries can be removed */ - if (LoadX->AM != AM65_IMM) { - D->Lhs.X.Flags |= LI_REMOVE; - } - if (LoadA->AM != AM65_IMM) { - D->Lhs.A.Flags |= LI_REMOVE; - } + D->Lhs.X.Flags |= LI_REMOVE; + D->Lhs.A.Flags |= LI_REMOVE; } else if ((D->Rhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT && (D->Rhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) { @@ -794,12 +790,8 @@ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer InsertEntry (D, X, D->IP++); /* Rhs load entries can be removed */ - if (LoadX->AM != AM65_IMM) { - D->Rhs.X.Flags |= LI_REMOVE; - } - if (LoadA->AM != AM65_IMM) { - D->Rhs.A.Flags |= LI_REMOVE; - } + D->Rhs.X.Flags |= LI_REMOVE; + D->Rhs.A.Flags |= LI_REMOVE; } else if ((D->Rhs.A.Flags & LI_DIRECT) != 0 && (D->Rhs.X.Flags & LI_DIRECT) != 0) { diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 053810b50..8c9d6dcb0 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2012, Ullrich von Bassewitz */ +/* (C) 1998-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -293,15 +293,15 @@ void PrintType (FILE* F, const Type* T) /* Recursive call */ PrintType (F, T + 1); if (T->A.L == UNSPECIFIED) { - fprintf (F, "[]"); + fprintf (F, " []"); } else { - fprintf (F, "[%ld]", T->A.L); + fprintf (F, " [%ld]", T->A.L); } return; case T_TYPE_PTR: /* Recursive call */ PrintType (F, T + 1); - fprintf (F, "*"); + fprintf (F, " *"); return; case T_TYPE_FUNC: fprintf (F, "function returning "); @@ -391,6 +391,12 @@ unsigned SizeOf (const Type* T) case T_VOID: return 0; /* Assume voids have size zero */ + /* Beware: There's a chance that this triggers problems in other parts + of the compiler. The solution is to fix the callers, because calling + SizeOf() with a function type as argument is bad. */ + case T_FUNC: + return 0; /* Size of function is unknown */ + case T_SCHAR: case T_UCHAR: return SIZEOF_CHAR; @@ -404,7 +410,6 @@ unsigned SizeOf (const Type* T) return SIZEOF_INT; case T_PTR: - case T_FUNC: /* Maybe pointer to function */ return SIZEOF_PTR; case T_LONG: @@ -659,7 +664,7 @@ Type* GetBaseElementType (Type* T) ** will return. Otherwise it will return the base element type, which means ** the element type that is not an array. */ -{ +{ while (IsTypeArray (T)) { ++T; } diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 598d0a228..92b3d0122 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2012, Ullrich von Bassewitz */ +/* (C) 1998-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -603,6 +603,16 @@ INLINE int IsQualCDecl (const Type* T) # define IsQualCDecl(T) (((T)->C & T_QUAL_CDECL) != 0) #endif +#if defined(HAVE_INLINE) +INLINE int IsQualCConv (const Type* T) +/* Return true if the given type has a calling convention qualifier */ +{ + return (T->C & T_QUAL_CCONV) != 0; +} +#else +# define IsQualCConv(T) (((T)->C & T_QUAL_CCONV) != 0) +#endif + int IsVariadicFunc (const Type* T) attribute ((const)); /* Return true if this is a function type or pointer to function type with ** variable parameter list diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 693c2116e..163084835 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2013, Ullrich von Bassewitz */ +/* (C) 1998-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -85,7 +85,7 @@ struct StructInitData { static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers); -/* Parse a type specificier */ +/* Parse a type specifier */ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers); /* Parse initialization of variables. Return the number of data bytes. */ @@ -335,18 +335,30 @@ static void FixQualifiers (Type* DataType) T = DataType; while (T->C != T_END) { if (IsTypePtr (T)) { + /* Calling convention qualifier on the pointer? */ + if (IsQualCConv (T)) { + /* Pull the convention off of the pointer */ + Q = T[0].C & T_QUAL_CCONV; + T[0].C &= ~T_QUAL_CCONV; - /* Fastcall qualifier on the pointer? */ - if (IsQualFastcall (T)) { - /* Pointer to function which is not fastcall? */ - if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) { - /* Move the fastcall qualifier from the pointer to - ** the function. - */ - T[0].C &= ~T_QUAL_FASTCALL; - T[1].C |= T_QUAL_FASTCALL; + /* Pointer to a function which doesn't have an explicit convention? */ + if (IsTypeFunc (T + 1)) { + if (IsQualCConv (T + 1)) { + if ((T[1].C & T_QUAL_CCONV) == Q) { + Warning ("Pointer duplicates function's calling convention"); + } else { + Error ("Function's and pointer's calling conventions are different"); + } + } else { + if (Q == T_QUAL_FASTCALL && IsVariadicFunc (T + 1)) { + Error ("Variadic-function pointers cannot be __fastcall__"); + } else { + /* Move the qualifier from the pointer to the function. */ + T[1].C |= Q; + } + } } else { - Error ("Invalid `_fastcall__' qualifier for pointer"); + Error ("Not pointer to a function; can't use a calling convention"); } } @@ -355,8 +367,8 @@ static void FixQualifiers (Type* DataType) if (Q == T_QUAL_NONE) { /* No address size qualifiers specified */ if (IsTypeFunc (T+1)) { - /* Pointer to function. Use the qualifier from the function - ** or the default if the function don't has one. + /* Pointer to function. Use the qualifier from the function, + ** or the default if the function doesn't have one. */ Q = (T[1].C & T_QUAL_ADDRSIZE); if (Q == T_QUAL_NONE) { @@ -368,7 +380,7 @@ static void FixQualifiers (Type* DataType) T[0].C |= Q; } else { /* We have address size qualifiers. If followed by a function, - ** apply these also to the function. + ** apply them to the function also. */ if (IsTypeFunc (T+1)) { TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE); @@ -489,7 +501,7 @@ static void ParseEnumDecl (void) static int ParseFieldWidth (Declaration* Decl) -/* Parse an optional field width. Returns -1 if no field width is speficied, +/* Parse an optional field width. Returns -1 if no field width is specified, ** otherwise the width of the field. */ { @@ -862,7 +874,7 @@ NextMember: if (CurTok.Tok != TOK_COMMA) { static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers) -/* Parse a type specificier */ +/* Parse a type specifier */ { ident Ident; SymEntry* Entry; @@ -1376,13 +1388,13 @@ static FuncDesc* ParseFuncDecl (void) static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) /* Recursively process declarators. Build a type array in reverse order. */ { - /* Read optional function or pointer qualifiers. These modify the - ** identifier or token to the right. For convenience, we allow the fastcall - ** qualifier also for pointers here. If it is a pointer-to-function, the - ** qualifier will later be transfered to the function itself. If it's a + /* Read optional function or pointer qualifiers. They modify the + ** identifier or token to the right. For convenience, we allow a calling + ** convention also for pointers here. If it's a pointer-to-function, the + ** qualifier later will be transfered to the function itself. If it's a ** pointer to something else, it will be flagged as an error. */ - TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_FASTCALL); + TypeCode Qualifiers = OptionalQualifiers (T_QUAL_ADDRSIZE | T_QUAL_CCONV); /* Pointer to something */ if (CurTok.Tok == TOK_STAR) { @@ -1390,10 +1402,10 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) /* Skip the star */ NextToken (); - /* Allow const, restrict and volatile qualifiers */ + /* Allow const, restrict, and volatile qualifiers */ Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT); - /* Parse the type, the pointer points to */ + /* Parse the type that the pointer points to */ Declarator (Spec, D, Mode); /* Add the type */ @@ -1443,7 +1455,7 @@ static void Declarator (const DeclSpec* Spec, Declaration* D, declmode_t Mode) /* We cannot specify fastcall for variadic functions */ if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) { - Error ("Variadic functions cannot be `__fastcall__'"); + Error ("Variadic functions cannot be __fastcall__"); Qualifiers &= ~T_QUAL_FASTCALL; } diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 03374a521..34cf550a2 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1,6 +1,7 @@ /* expr.c ** -** Ullrich von Bassewitz, 21.06.1998 +** 1998-06-21, Ullrich von Bassewitz +** 2015-06-26, Greg King */ @@ -49,6 +50,7 @@ /* Generator attributes */ #define GEN_NOPUSH 0x01 /* Don't push lhs */ #define GEN_COMM 0x02 /* Operator is commutative */ +#define GEN_NOFUNC 0x04 /* Not allowed for function pointers */ /* Map a generator function and its attributes to a token */ typedef struct { @@ -470,9 +472,11 @@ static void FunctionCall (ExprDesc* Expr) /* Handle function pointers transparently */ IsFuncPtr = IsTypeFuncPtr (Expr->Type); if (IsFuncPtr) { - - /* Check wether it's a fastcall function that has parameters */ - IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0); + /* Check whether it's a fastcall function that has parameters */ + IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && Func->ParamCount > 0 && + (AutoCDecl ? + IsQualFastcall (Expr->Type + 1) : + !IsQualCDecl (Expr->Type + 1)); /* Things may be difficult, depending on where the function pointer ** resides. If the function pointer is an expression of some sort @@ -517,7 +521,10 @@ static void FunctionCall (ExprDesc* Expr) } /* If we didn't inline the function, get fastcall info */ - IsFastcall = IsQualFastcall (Expr->Type); + IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && + (AutoCDecl ? + IsQualFastcall (Expr->Type) : + !IsQualCDecl (Expr->Type)); } /* Parse the parameter list */ @@ -1707,8 +1714,13 @@ void hie10 (ExprDesc* Expr) } else { Error ("Illegal indirection"); } - /* The * operator yields an lvalue */ - ED_MakeLVal (Expr); + /* If the expression points to an array, then don't convert the + ** address -- it already is the location of the first element. + */ + if (!IsTypeArray (Expr->Type)) { + /* The * operator yields an lvalue */ + ED_MakeLVal (Expr); + } } break; @@ -2031,6 +2043,11 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ Tok = CurTok.Tok; NextToken (); + /* If lhs is a function, convert it to pointer to function */ + if (IsTypeFunc (Expr->Type)) { + Expr->Type = PointerTo (Expr->Type); + } + /* Get the lhs on stack */ GetCodePos (&Mark1); ltype = TypeOf (Expr->Type); @@ -2048,6 +2065,11 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ /* Get the right hand side */ MarkedExprWithCheck (hienext, &Expr2); + /* If rhs is a function, convert it to pointer to function */ + if (IsTypeFunc (Expr2.Type)) { + Expr2.Type = PointerTo (Expr2.Type); + } + /* Check for a constant expression */ rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)); if (!rconst) { @@ -2055,6 +2077,22 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ LoadExpr (CF_NONE, &Expr2); } + /* Some operations aren't allowed on function pointers */ + if ((Gen->Flags & GEN_NOFUNC) != 0) { + /* Output only one message even if both sides are wrong */ + if (IsTypeFuncPtr (Expr->Type)) { + Error ("Invalid left operand for relational operator"); + /* Avoid further errors */ + ED_MakeConstAbsInt (Expr, 0); + ED_MakeConstAbsInt (&Expr2, 0); + } else if (IsTypeFuncPtr (Expr2.Type)) { + Error ("Invalid right operand for relational operator"); + /* Avoid further errors */ + ED_MakeConstAbsInt (Expr, 0); + ED_MakeConstAbsInt (&Expr2, 0); + } + } + /* Make sure, the types are compatible */ if (IsClassInt (Expr->Type)) { if (!IsClassInt (Expr2.Type) && !(IsClassPtr(Expr2.Type) && ED_IsNullPtr(Expr))) { @@ -2067,8 +2105,8 @@ static void hie_compare (const GenDesc* Ops, /* List of generators */ */ Type* left = Indirect (Expr->Type); Type* right = Indirect (Expr2.Type); - if (TypeCmp (left, right) < TC_EQUAL && left->C != T_VOID && right->C != T_VOID) { - /* Incomatible pointers */ + if (TypeCmp (left, right) < TC_QUAL_DIFF && left->C != T_VOID && right->C != T_VOID) { + /* Incompatible pointers */ Error ("Incompatible types"); } } else if (!ED_IsNullPtr (&Expr2)) { @@ -2352,7 +2390,6 @@ static void parseadd (ExprDesc* Expr) Type* lhst; /* Type of left hand side */ Type* rhst; /* Type of right hand side */ - /* Skip the PLUS token */ NextToken (); @@ -2535,7 +2572,7 @@ static void parseadd (ExprDesc* Expr) flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs */ - g_tosint (TypeOf (rhst)); /* Make sure, TOS is int */ + g_tosint (TypeOf (lhst)); /* Make sure TOS is int */ g_swap (CF_INT); /* Swap TOS and primary */ g_scale (CF_INT, CheckedPSizeOf (rhst)); /* Operate on pointers, result type is a pointer */ @@ -2569,7 +2606,6 @@ static void parseadd (ExprDesc* Expr) /* Condition codes not set */ ED_MarkAsUntested (Expr); - } @@ -2589,6 +2625,13 @@ static void parsesub (ExprDesc* Expr) int rscale; /* Scale factor for the result */ + /* lhs cannot be function or pointer to function */ + if (IsTypeFunc (Expr->Type) || IsTypeFuncPtr (Expr->Type)) { + Error ("Invalid left operand for binary operator `-'"); + /* Make it pointer to char to avoid further errors */ + Expr->Type = type_uchar; + } + /* Skip the MINUS token */ NextToken (); @@ -2605,6 +2648,13 @@ static void parsesub (ExprDesc* Expr) /* Parse the right hand side */ MarkedExprWithCheck (hie9, &Expr2); + /* rhs cannot be function or pointer to function */ + if (IsTypeFunc (Expr2.Type) || IsTypeFuncPtr (Expr2.Type)) { + Error ("Invalid right operand for binary operator `-'"); + /* Make it pointer to char to avoid further errors */ + Expr2.Type = type_uchar; + } + /* Check for a constant rhs expression */ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { @@ -2764,11 +2814,11 @@ static void hie6 (ExprDesc* Expr) /* Handle greater-than type comparators */ { static const GenDesc hie6_ops [] = { - { TOK_LT, GEN_NOPUSH, g_lt }, - { TOK_LE, GEN_NOPUSH, g_le }, - { TOK_GE, GEN_NOPUSH, g_ge }, - { TOK_GT, GEN_NOPUSH, g_gt }, - { TOK_INVALID, 0, 0 } + { TOK_LT, GEN_NOPUSH | GEN_NOFUNC, g_lt }, + { TOK_LE, GEN_NOPUSH | GEN_NOFUNC, g_le }, + { TOK_GE, GEN_NOPUSH | GEN_NOFUNC, g_ge }, + { TOK_GT, GEN_NOPUSH | GEN_NOFUNC, g_gt }, + { TOK_INVALID, 0, 0 } }; hie_compare (hie6_ops, Expr, ShiftExpr); } diff --git a/src/cc65/function.c b/src/cc65/function.c index d9f1eeac3..22b305739 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000-2012, Ullrich von Bassewitz */ +/* (C) 2000-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -460,6 +460,9 @@ void NewFunc (SymEntry* Func) */ if (D->ParamCount > 0 || (D->Flags & FD_VARIADIC) != 0) { g_importmainargs (); + + /* The start-up code doesn't fast-call main(). */ + Func->Type->C |= T_QUAL_CDECL; } /* Determine if this is a main function in a C99 environment that @@ -478,13 +481,12 @@ void NewFunc (SymEntry* Func) PushLiteralPool (Func); /* If this is a fastcall function, push the last parameter onto the stack */ - if (IsQualFastcall (Func->Type) && D->ParamCount > 0) { - + if ((D->Flags & FD_VARIADIC) == 0 && D->ParamCount > 0 && + (AutoCDecl ? + IsQualFastcall (Func->Type) : + !IsQualCDecl (Func->Type))) { unsigned Flags; - /* Fastcall functions may never have an ellipsis or the compiler is buggy */ - CHECK ((D->Flags & FD_VARIADIC) == 0); - /* Generate the push */ if (IsTypeFunc (D->LastParam->Type)) { /* Pointer to function */ diff --git a/src/cc65/global.c b/src/cc65/global.c index e2800a65e..dbdd72f3c 100644 --- a/src/cc65/global.c +++ b/src/cc65/global.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2012, Ullrich von Bassewitz */ +/* (C) 1998-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -44,6 +44,7 @@ unsigned char AddSource = 0; /* Add source lines as comments */ +unsigned char AutoCDecl = 0; /* Make functions default to __cdecl__ */ unsigned char DebugInfo = 0; /* Add debug info to the obj */ unsigned char PreprocessOnly = 0; /* Just preprocess the input */ unsigned char DebugOptOutput = 0; /* Output debug stuff */ diff --git a/src/cc65/global.h b/src/cc65/global.h index 2abd78601..8b0af5a83 100644 --- a/src/cc65/global.h +++ b/src/cc65/global.h @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2012, Ullrich von Bassewitz */ +/* (C) 1998-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -52,6 +52,7 @@ /* Options */ extern unsigned char AddSource; /* Add source lines as comments */ +extern unsigned char AutoCDecl; /* Make functions default to __cdecl__ */ extern unsigned char DebugInfo; /* Add debug info to the obj */ extern unsigned char PreprocessOnly; /* Just preprocess the input */ extern unsigned char DebugOptOutput; /* Output debug stuff */ diff --git a/src/cc65/main.c b/src/cc65/main.c index 34688e97e..1041b8fa2 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000-2013, Ullrich von Bassewitz */ +/* (C) 2000-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -104,6 +104,7 @@ static void Usage (void) "\n" "Long options:\n" " --add-source\t\t\tInclude source as comment\n" + " --all-cdecl\t\t\tMake functions default to __cdecl__\n" " --bss-name seg\t\tSet the name of the BSS segment\n" " --check-stack\t\t\tGenerate stack overflow checks\n" " --code-name seg\t\tSet the name of the CODE segment\n" @@ -258,6 +259,14 @@ static void SetSys (const char* Sys) DefineNumericMacro ("__SIM65C02__", 1); break; + case TGT_OSIC1P: + DefineNumericMacro ("__OSIC1P__", 1); + break; + + case TGT_PCENGINE: + DefineNumericMacro ("__PCE__", 1); + break; + default: AbEnd ("Unknown target system type %d", Target); } @@ -346,6 +355,15 @@ static void OptAddSource (const char* Opt attribute ((unused)), +static void OptAllCDecl (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Make functions default to cdecl instead of fastcall. */ +{ + AutoCDecl = 1; +} + + + static void OptBssName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --bss-name option */ { @@ -786,6 +804,7 @@ int main (int argc, char* argv[]) /* Program long options */ static const LongOpt OptTab[] = { { "--add-source", 0, OptAddSource }, + { "--all-cdecl", 0, OptAllCDecl }, { "--bss-name", 1, OptBssName }, { "--check-stack", 0, OptCheckStack }, { "--code-name", 1, OptCodeName }, diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index a5ab4897e..99ce6acc1 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -321,7 +321,7 @@ static void NewStyleComment (void) /* Remove a new style C comment from line. */ { /* Beware: Because line continuation chars are handled when reading - ** lines, we may only skip til the end of the source line, which + ** lines, we may only skip until the end of the source line, which ** may not be the same as the end of the input line. The end of the ** source line is denoted by a lf (\n) character. */ diff --git a/src/cc65/symentry.c b/src/cc65/symentry.c index aa5949f97..980ee27f2 100644 --- a/src/cc65/symentry.c +++ b/src/cc65/symentry.c @@ -126,19 +126,19 @@ void DumpSymEntry (FILE* F, const SymEntry* E) /* Print the assembler name if we have one */ if (E->AsmName) { fprintf (F, " AsmName: %s\n", E->AsmName); - } + } /* Print the flags */ SymFlags = E->Flags; - fprintf (F, " Flags: "); + fprintf (F, " Flags:"); for (I = 0; I < sizeof (Flags) / sizeof (Flags[0]) && SymFlags != 0; ++I) { if ((SymFlags & Flags[I].Val) == Flags[I].Val) { SymFlags &= ~Flags[I].Val; - fprintf (F, "%s ", Flags[I].Name); + fprintf (F, " %s", Flags[I].Name); } } if (SymFlags != 0) { - fprintf (F, "%04X", SymFlags); + fprintf (F, " 0x%05X", SymFlags); } fprintf (F, "\n"); diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 1f63e9430..fdf459873 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -813,6 +813,25 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) } } + /* If a static declaration follows a non-static declaration, then + ** warn about the conflict. (It will compile a public declaration.) + */ + if ((Flags & SC_EXTERN) == 0 && (Entry->Flags & SC_EXTERN) != 0) { + Warning ("static declaration follows non-static declaration of `%s'.", Name); + } + + /* An extern declaration must not change the current linkage. */ + if (IsFunc || (Flags & (SC_EXTERN | SC_DEF)) == SC_EXTERN) { + Flags &= ~SC_EXTERN; + } + + /* If a public declaration follows a static declaration, then + ** warn about the conflict. (It will compile a public declaration.) + */ + if ((Flags & SC_EXTERN) != 0 && (Entry->Flags & SC_EXTERN) == 0) { + Warning ("public declaration follows static declaration of `%s'.", Name); + } + /* Add the new flags */ Entry->Flags |= Flags; diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 67941026b..673dfa163 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2008 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2015, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -37,6 +37,7 @@ /* cc65 */ #include "funcdesc.h" +#include "global.h" #include "symtab.h" #include "typecmp.h" @@ -245,23 +246,36 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) return; } } + + if (LeftType == T_TYPE_FUNC) { + /* If a calling convention wasn't set explicitly, + ** then assume the default one. + */ + if ((LeftQual & T_QUAL_CCONV) == T_QUAL_NONE) { + LeftQual |= (AutoCDecl || IsVariadicFunc (lhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL; + } + if ((RightQual & T_QUAL_CCONV) == T_QUAL_NONE) { + RightQual |= (AutoCDecl || IsVariadicFunc (rhs)) ? T_QUAL_CDECL : T_QUAL_FASTCALL; + } + } + if (LeftQual != RightQual) { /* On the first indirection level, different qualifiers mean - ** that the types are still compatible. On the second level, - ** this is a (maybe minor) error, so we create a special - ** return code, since a qualifier is dropped from a pointer. - ** Starting from the next level, the types are incompatible - ** if the qualifiers differ. + ** that the types still are compatible. On the second level, + ** that is a (maybe minor) error. We create a special return-code + ** if a qualifier is dropped from a pointer. But, different calling + ** conventions are incompatible. Starting from the next level, + ** the types are incompatible if the qualifiers differ. */ + /* (Debugging statement) */ /* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */ switch (Indirections) { - case 0: SetResult (Result, TC_STRICT_COMPATIBLE); break; case 1: - /* A non const value on the right is compatible to a + /* A non-const value on the right is compatible to a ** const one to the left, same for volatile. */ if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) || @@ -270,7 +284,11 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) } else { SetResult (Result, TC_STRICT_COMPATIBLE); } - break; + + if (LeftType != T_TYPE_FUNC || (LeftQual & T_QUAL_CCONV) == (RightQual & T_QUAL_CCONV)) { + break; + } + /* else fall through */ default: SetResult (Result, TC_INCOMPATIBLE); @@ -280,7 +298,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* Check for special type elements */ switch (LeftType) { - case T_TYPE_PTR: ++Indirections; break; diff --git a/src/cl65/main.c b/src/cl65/main.c index a0a6ed02b..4268a569b 100644 --- a/src/cl65/main.c +++ b/src/cl65/main.c @@ -148,7 +148,7 @@ static char* TargetLib = 0; #if defined(NEED_SPAWN) -# if defined(SPAWN_AMIGA) +# if defined(_AMIGA) # include "spawn-amiga.inc" # else # include "spawn-unix.inc" diff --git a/src/cl65/spawn-amiga.inc b/src/cl65/spawn-amiga.inc index 5d1b60ea3..ce13ae132 100644 --- a/src/cl65/spawn-amiga.inc +++ b/src/cl65/spawn-amiga.inc @@ -38,8 +38,8 @@ /* Mode argument for spawn. This value is ignored by the function and only - * provided for DOS/Windows compatibility. - */ +** provided for DOS/Windows compatibility. +*/ #ifndef P_WAIT #define P_WAIT 0 #endif @@ -55,11 +55,11 @@ int spawnvp (int Mode attribute ((unused)), const char* File attribute ((unused)), char* const argv []) -/* Execute the given program searching and wait til it terminates. The Mode - * argument is ignored (compatibility only). The result of the function is - * the return code of the program. The function will terminate the program - * on errors. - */ +/* Execute the given program searching and wait until it terminates. The Mode +** argument is ignored (compatibility only). The result of the function is +** the return code of the program. The function will terminate the program +** on errors. +*/ { int Status; StrBuf Command = AUTO_STRBUF_INITIALIZER; diff --git a/src/cl65/spawn-unix.inc b/src/cl65/spawn-unix.inc index fc5125c34..283285c76 100644 --- a/src/cl65/spawn-unix.inc +++ b/src/cl65/spawn-unix.inc @@ -48,8 +48,8 @@ /* Mode argument for spawn. This value is ignored by the function and only - * provided for DOS/Windows compatibility. - */ +** provided for DOS/Windows compatibility. +*/ #ifndef P_WAIT #define P_WAIT 0 #endif @@ -63,11 +63,11 @@ int spawnvp (int Mode attribute ((unused)), const char* File, char* const argv []) -/* Execute the given program searching and wait til it terminates. The Mode - * argument is ignored (compatibility only). The result of the function is - * the return code of the program. The function will terminate the program - * on errors. - */ +/* Execute the given program searching and wait until it terminates. The Mode +** argument is ignored (compatibility only). The result of the function is +** the return code of the program. The function will terminate the program +** on errors. +*/ { int Status = 0; @@ -99,7 +99,7 @@ int spawnvp (int Mode attribute ((unused)), const char* File, char* const argv [ } /* Only the father goes here, we place a return here regardless of that - * to avoid compiler warnings. - */ + ** to avoid compiler warnings. + */ return WEXITSTATUS (Status); } diff --git a/src/common/cmdline.c b/src/common/cmdline.c index 716df1efb..0f6622934 100644 --- a/src/common/cmdline.c +++ b/src/common/cmdline.c @@ -161,7 +161,7 @@ static void ExpandFile (CmdLine* L, const char* Name) -void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName) +void InitCmdLine (int* aArgCount, char*** aArgVec, const char* aProgName) /* Initialize command line parsing. aArgVec is the argument array terminated by ** a NULL pointer (as usual), ArgCount is the number of valid arguments in the ** array. Both arguments are remembered in static storage. @@ -171,7 +171,7 @@ void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName) int I; /* Get the program name from argv[0] but strip a path */ - if (*(aArgVec)[0] == 0) { + if ((*aArgVec)[0] == 0) { /* Use the default name given */ ProgName = aProgName; } else { @@ -190,7 +190,7 @@ void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName) ** special handling for arguments preceeded by the '@' sign - these are ** actually files containing arguments. */ - for (I = 0; I < *aArgCount; ++I) { + for (I = 0; I <= *aArgCount; ++I) { /* Get the next argument */ char* Arg = (*aArgVec)[I]; @@ -210,11 +210,11 @@ void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName) } /* Store the new argument list in a safe place... */ - ArgCount = L.Count; + ArgCount = L.Count - 1; ArgVec = L.Vec; /* ...and pass back the changed data also */ - *aArgCount = L.Count; + *aArgCount = L.Count - 1; *aArgVec = L.Vec; } diff --git a/src/common/cmdline.h b/src/common/cmdline.h index b18906c7a..1caf0cfb6 100644 --- a/src/common/cmdline.h +++ b/src/common/cmdline.h @@ -71,7 +71,7 @@ struct LongOpt { -void InitCmdLine (int* aArgCount, char** aArgVec[], const char* aProgName); +void InitCmdLine (int* aArgCount, char*** aArgVec, const char* aProgName); /* Initialize command line parsing. aArgVec is the argument array terminated by ** a NULL pointer (as usual), ArgCount is the number of valid arguments in the ** array. Both arguments are remembered in static storage. diff --git a/src/common/target.c b/src/common/target.c index ffb342e25..60b9af660 100644 --- a/src/common/target.c +++ b/src/common/target.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000-2011, Ullrich von Bassewitz */ +/* (C) 2000-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -50,7 +50,7 @@ /* Translation table with direct (no) translation */ -static unsigned char CTNone[256] = { +static const unsigned char CTNone[256] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, @@ -69,8 +69,8 @@ static unsigned char CTNone[256] = { 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF, }; -/* Translation table ISO-8859-1 -> ATASCII */ -static const unsigned char CTAtari [256] = { +/* Translation table ISO-8859-1 -> AtASCII */ +static const unsigned char CTAtari[256] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0xFD,0x08,0x7F,0x9B,0x0B,0x7D,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, @@ -89,8 +89,28 @@ static const unsigned char CTAtari [256] = { 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF, }; -/* Translation table ISO-8859-1 -> PETSCII */ -static const unsigned char CTPET [256] = { +/* Translation table ISO-8859-1 -> OSASCII */ +static const unsigned char CTOSI[256] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7D,0x7C,0x7F,0x7E, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF, +}; + +/* Translation table ISO-8859-1 -> PetSCII */ +static const unsigned char CTPET[256] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F, 0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, @@ -142,6 +162,8 @@ static const TargetEntry TargetMap[] = { { "module", TGT_MODULE }, { "nes", TGT_NES }, { "none", TGT_NONE }, + { "osic1p", TGT_OSIC1P }, + { "pce", TGT_PCENGINE }, { "pet", TGT_PET }, { "plus4", TGT_PLUS4 }, { "sim6502", TGT_SIM6502 }, @@ -167,6 +189,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = { { "plus4", CPU_6502, BINFMT_BINARY, CTPET }, { "cbm510", CPU_6502, BINFMT_BINARY, CTPET }, { "cbm610", CPU_6502, BINFMT_BINARY, CTPET }, + { "osic1p", CPU_6502, BINFMT_BINARY, CTOSI }, { "pet", CPU_6502, BINFMT_BINARY, CTPET }, { "bbc", CPU_6502, BINFMT_BINARY, CTNone }, { "apple2", CPU_6502, BINFMT_BINARY, CTNone }, @@ -180,6 +203,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = { { "lynx", CPU_65C02, BINFMT_BINARY, CTNone }, { "sim6502", CPU_6502, BINFMT_BINARY, CTNone }, { "sim65c02", CPU_65C02, BINFMT_BINARY, CTNone }, + { "pce", CPU_HUC6280, BINFMT_BINARY, CTNone }, }; /* Target system */ diff --git a/src/common/target.h b/src/common/target.h index 72dffe382..3ea562aa6 100644 --- a/src/common/target.h +++ b/src/common/target.h @@ -64,6 +64,7 @@ typedef enum { TGT_PLUS4, TGT_CBM510, TGT_CBM610, + TGT_OSIC1P, TGT_PET, TGT_BBC, TGT_APPLE2, @@ -77,6 +78,7 @@ typedef enum { TGT_LYNX, TGT_SIM6502, TGT_SIM65C02, + TGT_PCENGINE, TGT_COUNT /* Number of target systems */ } target_t; diff --git a/src/common/version.c b/src/common/version.c index d2fcf4f40..4e61a5f83 100644 --- a/src/common/version.c +++ b/src/common/version.c @@ -47,7 +47,7 @@ #define VER_MAJOR 2U -#define VER_MINOR 14U +#define VER_MINOR 15U diff --git a/src/da65/attrtab.c b/src/da65/attrtab.c index 1cfb5ba45..a9143584a 100644 --- a/src/da65/attrtab.c +++ b/src/da65/attrtab.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000-2006 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2014, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -66,6 +66,18 @@ void AddrCheck (unsigned Addr) +attr_t GetAttr (unsigned Addr) +/* Return the attribute for the given address */ +{ + /* Check the given address */ + AddrCheck (Addr); + + /* Return the attribute */ + return AttrTab[Addr]; +} + + + int SegmentDefined (unsigned Start, unsigned End) /* Return true if the atSegment bit is set somewhere in the given range */ { @@ -79,14 +91,18 @@ int SegmentDefined (unsigned Start, unsigned End) -int HaveSegmentChange (unsigned Addr) -/* Return true if the segment change attribute is set for the given address */ +int IsSegmentEnd (unsigned Addr) +/* Return true if a segment ends at the given address */ { - /* Check the given address */ - AddrCheck (Addr); + return (GetAttr (Addr) & atSegmentEnd) != 0x0000; +} - /* Return the attribute */ - return (AttrTab[Addr] & atSegmentChange) != 0; + + +int IsSegmentStart (unsigned Addr) +/* Return true if a segment starts at the given address */ +{ + return (GetAttr (Addr) & atSegmentStart) != 0x0000; } @@ -145,18 +161,6 @@ void MarkAddr (unsigned Addr, attr_t Attr) -attr_t GetAttr (unsigned Addr) -/* Return the attribute for the given address */ -{ - /* Check the given address */ - AddrCheck (Addr); - - /* Return the attribute */ - return AttrTab[Addr]; -} - - - attr_t GetStyleAttr (unsigned Addr) /* Return the style attribute for the given address */ { diff --git a/src/da65/attrtab.h b/src/da65/attrtab.h index c9fb9c35f..18515ce49 100644 --- a/src/da65/attrtab.h +++ b/src/da65/attrtab.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000-2006 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2014, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -47,33 +47,34 @@ typedef enum attr_t { /* Styles */ - atDefault = 0x0000, /* Default style */ - atCode = 0x0001, - atIllegal = 0x0002, - atByteTab = 0x0003, /* Same as illegal */ - atDByteTab = 0x0004, - atWordTab = 0x0005, - atDWordTab = 0x0006, - atAddrTab = 0x0007, - atRtsTab = 0x0008, - atTextTab = 0x0009, - atSkip = 0x000A, /* Skip code completely */ + atDefault = 0x0000, /* Default style */ + atCode = 0x0001, + atIllegal = 0x0002, + atByteTab = 0x0003, /* Same as illegal */ + atDByteTab = 0x0004, + atWordTab = 0x0005, + atDWordTab = 0x0006, + atAddrTab = 0x0007, + atRtsTab = 0x0008, + atTextTab = 0x0009, + atSkip = 0x000A, /* Skip code completely */ /* Label flags */ - atNoLabel = 0x0000, /* No label for this address */ - atExtLabel = 0x0010, /* External label */ - atIntLabel = 0x0020, /* Internally generated label */ - atDepLabel = 0x0040, /* Dependent label */ - atUnnamedLabel = 0x0080, /* Unnamed label */ + atNoLabel = 0x0000, /* No label for this address */ + atExtLabel = 0x0010, /* External label */ + atIntLabel = 0x0020, /* Internally generated label */ + atDepLabel = 0x0040, /* Dependent label */ + atUnnamedLabel = 0x0080, /* Unnamed label */ - atLabelDefined = 0x0100, /* True if we defined the label */ + atLabelDefined = 0x0100, /* True if we defined the label */ - atStyleMask = 0x000F, /* Output style */ - atLabelMask = 0x00F0, /* Label information */ + atStyleMask = 0x000F, /* Output style */ + atLabelMask = 0x00F0, /* Label information */ /* Segment */ - atSegment = 0x0100, /* Code is in a segment */ - atSegmentChange = 0x0200, /* Either segment start or segment end */ + atSegment = 0x0100, /* Code is in a segment */ + atSegmentEnd = 0x0200, /* Segment end */ + atSegmentStart = 0x0400, /* Segment start */ } attr_t; @@ -87,11 +88,17 @@ typedef enum attr_t { void AddrCheck (unsigned Addr); /* Check if the given address has a valid range */ +attr_t GetAttr (unsigned Addr); +/* Return the attribute for the given address */ + int SegmentDefined (unsigned Start, unsigned End); /* Return true if the atSegment bit is set somewhere in the given range */ -int HaveSegmentChange (unsigned Addr); -/* Return true if the segment change attribute is set for the given address */ +int IsSegmentEnd (unsigned Addr); +/* Return true if a segment ends at the given address */ + +int IsSegmentStart (unsigned Addr); +/* Return true if a segment starts at the given address */ unsigned GetGranularity (attr_t Style); /* Get the granularity for the given style */ @@ -102,9 +109,6 @@ void MarkRange (unsigned Start, unsigned End, attr_t Attr); void MarkAddr (unsigned Addr, attr_t Attr); /* Mark an address with an attribute */ -attr_t GetAttr (unsigned Addr); -/* Return the attribute for the given address */ - attr_t GetStyleAttr (unsigned Addr); /* Return the style attribute for the given address */ @@ -114,5 +118,4 @@ attr_t GetLabelAttr (unsigned Addr); /* End of attrtab.h */ - #endif diff --git a/src/da65/data.c b/src/da65/data.c index f4c37818f..7355e60d1 100644 --- a/src/da65/data.c +++ b/src/da65/data.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000-2007 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2014, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -65,12 +65,12 @@ static unsigned GetSpan (attr_t Style) attr_t Attr; if (MustDefLabel(PC+Count)) { break; - } + } Attr = GetAttr (PC+Count); if ((Attr & atStyleMask) != Style) { break; } - if ((Attr & atSegmentChange)) { + if ((Attr & (atSegmentStart | atSegmentEnd))) { break; } ++Count; diff --git a/src/da65/infofile.c b/src/da65/infofile.c index 4ee1ffd79..e8ce66cf7 100644 --- a/src/da65/infofile.c +++ b/src/da65/infofile.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000-2011, Ullrich von Bassewitz */ +/* (C) 2000-2014, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -748,16 +748,13 @@ static void SegmentSection (void) if (Start < 0) { InfoError ("Start address is missing"); } - if (Start == End) { - InfoError ("Segment is empty"); - } if (Start > End) { InfoError ("Start address of segment is greater than end address"); } /* Check that segments do not overlap */ if (SegmentDefined ((unsigned) Start, (unsigned) End)) { - InfoError ("Segments cannot overlap"); + InfoError ("Segments must not overlap"); } /* Remember the segment data */ diff --git a/src/da65/main.c b/src/da65/main.c index a819f9771..8c37e1ae2 100644 --- a/src/da65/main.c +++ b/src/da65/main.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 1998-2011, Ullrich von Bassewitz */ +/* (C) 1998-2014, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -60,6 +60,7 @@ #include "opctable.h" #include "output.h" #include "scanner.h" +#include "segment.h" @@ -347,6 +348,8 @@ static void OptVersion (const char* Opt attribute ((unused)), static void OneOpcode (unsigned RemainingBytes) /* Disassemble one opcode */ { + unsigned I; + /* Get the opcode from the current address */ unsigned char OPC = GetCodeByte (PC); @@ -356,6 +359,14 @@ static void OneOpcode (unsigned RemainingBytes) /* Get the output style for the current PC */ attr_t Style = GetStyleAttr (PC); + /* If a segment begins here, then name that segment. + ** Note that the segment is named even if its code is being skipped, + ** because some of its later code might not be skipped. + */ + if (IsSegmentStart (PC)) { + StartSegment (GetSegmentStartName (PC), GetSegmentAddrSize (PC)); + } + /* If we have a label at this address, output the label and an attached ** comment, provided that we aren't in a skip area. */ @@ -371,7 +382,8 @@ static void OneOpcode (unsigned RemainingBytes) ** - ...if we have enough bytes remaining for the code at this address. ** - ...if the current instruction is valid for the given CPU. ** - ...if there is no label somewhere between the instruction bytes. - ** If any of these conditions is false, switch to data mode. + ** - ...if there is no segment change between the instruction bytes. + ** If any one of those conditions is false, switch to data mode. */ if (Style == atDefault) { if (D->Size > RemainingBytes) { @@ -381,9 +393,15 @@ static void OneOpcode (unsigned RemainingBytes) Style = atIllegal; MarkAddr (PC, Style); } else { - unsigned I; - for (I = 1; I < D->Size; ++I) { - if (HaveLabel (PC+I) || HaveSegmentChange (PC+I)) { + for (I = PC + D->Size; --I > PC; ) { + if (HaveLabel (I) || IsSegmentStart (I)) { + Style = atIllegal; + MarkAddr (PC, Style); + break; + } + } + for (I = 0; I < D->Size - 1u; ++I) { + if (IsSegmentEnd (PC + I)) { Style = atIllegal; MarkAddr (PC, Style); break; @@ -406,7 +424,6 @@ static void OneOpcode (unsigned RemainingBytes) */ if (D->Size <= RemainingBytes) { /* Output labels within the next insn */ - unsigned I; for (I = 1; I < D->Size; ++I) { ForwardLabel (I); } @@ -453,7 +470,16 @@ static void OneOpcode (unsigned RemainingBytes) DataByteLine (1); ++PC; break; + } + /* Change back to the default CODE segment if + ** a named segment stops at the current address. + */ + for (I = D->Size; I >= 1; --I) { + if (IsSegmentEnd (PC - I)) { + EndSegment (); + break; + } } } diff --git a/src/da65/output.c b/src/da65/output.c index 9098d7d37..4daacb1ee 100644 --- a/src/da65/output.c +++ b/src/da65/output.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000-2009, Ullrich von Bassewitz */ +/* (C) 2000-2014, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -63,6 +63,8 @@ static unsigned Col = 1; /* Current column */ static unsigned Line = 0; /* Current line on page */ static unsigned Page = 1; /* Current output page */ +static const char* SegmentName = 0; /* Name of current segment */ + /*****************************************************************************/ @@ -223,23 +225,6 @@ void DefConst (const char* Name, const char* Comment, unsigned Addr) -void StartSegment (const char* Name, unsigned AddrSize) -/* Start a segment */ -{ - if (Pass == PassCount) { - Output (".segment"); - Indent (ACol); - if (AddrSize == ADDR_SIZE_DEFAULT) { - Output ("\"%s\"", Name); - } else { - Output ("\"%s\": %s", Name, AddrSizeToStr (AddrSize)); - } - LineFeed (); - } -} - - - void DataByteLine (unsigned ByteCount) /* Output a line with bytes */ { @@ -335,6 +320,39 @@ void SeparatorLine (void) +void StartSegment (const char* Name, unsigned AddrSize) +/* Start a segment */ +{ + if (Pass == PassCount) { + LineFeed (); + Output (".segment"); + Indent (ACol); + SegmentName = Name; + Output ("\"%s\"", Name); + if (AddrSize != ADDR_SIZE_DEFAULT) { + Output (": %s", AddrSizeToStr (AddrSize)); + } + LineFeed (); + LineFeed (); + } +} + + + +void EndSegment (void) +/* End a segment */ +{ + LineFeed (); + Output ("; End of \"%s\" segment", SegmentName); + LineFeed (); + SeparatorLine (); + Output (".code"); + LineFeed (); + LineFeed (); +} + + + void UserComment (const char* Comment) /* Output a comment line */ { diff --git a/src/da65/output.h b/src/da65/output.h index ad5f8d34e..13ea0cc85 100644 --- a/src/da65/output.h +++ b/src/da65/output.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000-2007 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2000-2014, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -74,12 +74,6 @@ void DefForward (const char* Name, const char* Comment, unsigned Offs); void DefConst (const char* Name, const char* Comment, unsigned Addr); /* Define an address constant */ - -void StartSegment (const char* Name, unsigned AddrSize); -/* Start a segment */ - -void EndSegment (void); -/* End a segment */ void OneDataByte (void); /* Output a .byte line with the current code byte */ @@ -99,6 +93,12 @@ void DataDWordLine (unsigned ByteCount); void SeparatorLine (void); /* Print a separator line */ +void StartSegment (const char* Name, unsigned AddrSize); +/* Start a segment */ + +void EndSegment (void); +/* End a segment */ + void UserComment (const char* Comment); /* Output a comment line */ @@ -111,5 +111,4 @@ void OutputSettings (void); /* End of output.h */ - #endif diff --git a/src/da65/segment.c b/src/da65/segment.c index cad2096ff..12d4cf656 100644 --- a/src/da65/segment.c +++ b/src/da65/segment.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2007 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2007-2014, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -58,18 +58,15 @@ typedef struct Segment Segment; struct Segment { Segment* NextStart; /* Pointer to next segment */ - Segment* NextEnd; /* Pointer to next segment */ unsigned long Start; - unsigned long End; unsigned AddrSize; char Name[1]; /* Name, dynamically allocated */ }; -/* Tables containing the segments. A segment is inserted using it's hash -** value. Collision is done by single linked lists. +/* Table containing the segments. A segment is inserted using its hash +** value. Collisions are handled by single-linked lists. */ static Segment* StartTab[HASH_SIZE]; /* Table containing segment starts */ -static Segment* EndTab[HASH_SIZE]; /* Table containing segment ends */ @@ -90,20 +87,53 @@ void AddAbsSegment (unsigned Start, unsigned End, const char* Name) /* Fill in the data */ S->Start = Start; - S->End = End; S->AddrSize = ADDR_SIZE_ABS; memcpy (S->Name, Name, Len + 1); - /* Insert the segment into the hash tables */ + /* Insert the segment into the hash table */ S->NextStart = StartTab[Start % HASH_SIZE]; StartTab[Start % HASH_SIZE] = S; - S->NextEnd = EndTab[End % HASH_SIZE]; - EndTab[End % HASH_SIZE] = S; /* Mark start and end of the segment */ - MarkAddr (Start, atSegmentChange); - MarkAddr (End, atSegmentChange); + MarkAddr (Start, atSegmentStart); + MarkAddr (End, atSegmentEnd); /* Mark the addresses within the segment */ MarkRange (Start, End, atSegment); } + + + +char* GetSegmentStartName (unsigned Addr) +/* Return the name of the segment which starts at the given address */ +{ + Segment* S = StartTab[Addr % HASH_SIZE]; + + /* Search the collision list for the exact address */ + while (S != 0) { + if (S->Start == Addr) { + return S->Name; + } + S = S->NextStart; + } + + return 0; +} + + + +unsigned GetSegmentAddrSize (unsigned Addr) +/* Return the address size of the segment which starts at the given address */ +{ + Segment* S = StartTab[Addr % HASH_SIZE]; + + /* Search the collision list for the exact address */ + while (S != 0) { + if (S->Start == Addr) { + return S->AddrSize; + } + S = S->NextStart; + } + + return 0; +} diff --git a/src/da65/segment.h b/src/da65/segment.h index 14700ba99..b1423bb41 100644 --- a/src/da65/segment.h +++ b/src/da65/segment.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2007 Ullrich von Bassewitz */ -/* Roemerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2007-2014, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -47,8 +47,13 @@ void AddAbsSegment (unsigned Start, unsigned End, const char* Name); /* Add an absolute segment to the segment table */ +char* GetSegmentStartName (unsigned Addr); +/* Return the name of the segment which starts at the given address */ + +unsigned GetSegmentAddrSize (unsigned Addr); +/* Return the address size of the segment which starts at the given address */ + /* End of segment.h */ - #endif diff --git a/src/dbginfo/dbgsh.c b/src/dbginfo/dbgsh.c index 41200e86a..ba5d83849 100644 --- a/src/dbginfo/dbgsh.c +++ b/src/dbginfo/dbgsh.c @@ -1885,7 +1885,7 @@ int main (int argc, char* argv[]) ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0])); } - /* Loop til program end */ + /* Loop until program end */ while (!Terminate) { /* Output a prompt, then read the input */ diff --git a/src/ld65/config.c b/src/ld65/config.c index 46e9a48fb..8e7a049c7 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1769,12 +1769,12 @@ static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr) unsigned CfgProcess (void) -/* Process the config file after reading in object files and libraries. This -** includes postprocessing of the config file data but also assigning segments -** and defining segment/memory area related symbols. The function will return -** the number of memory area overflows (so zero means anything went ok). +/* Process the config file, after reading in object files and libraries. This +** includes postprocessing of the config file data; but also assigning segments, +** and defining segment/memory-area related symbols. The function will return +** the number of memory area overflows (so, zero means everything went OK). ** In case of overflows, a short mapfile can be generated later, to ease the -** task of rearranging segments for the user. +** user's task of re-arranging segments. */ { unsigned Overflows = 0; @@ -1788,12 +1788,11 @@ unsigned CfgProcess (void) /* Postprocess segments */ ProcessSegments (); - /* Walk through each of the memory sections. Add up the sizes and check + /* Walk through each of the memory sections. Add up the sizes; and, check ** for an overflow of the section. Assign the start addresses of the - ** segments while doing this. + ** segments while doing that. */ for (I = 0; I < CollCount (&MemoryAreas); ++I) { - unsigned J; unsigned long Addr; @@ -1806,7 +1805,7 @@ unsigned CfgProcess (void) /* Remember if this is a relocatable memory area */ M->Relocatable = RelocatableBinFmt (M->F->Format); - /* Resolve the start address expression, remember the start address + /* Resolve the start address expression, remember the start address, ** and mark the memory area as placed. */ if (!IsConstExpr (M->StartExpr)) { @@ -1843,18 +1842,16 @@ unsigned CfgProcess (void) /* Walk through the segments in this memory area */ for (J = 0; J < CollCount (&M->SegList); ++J) { - /* Get the segment */ SegDesc* S = CollAtUnchecked (&M->SegList, J); /* Remember the start address before handling this segment */ unsigned long StartAddr = Addr; - /* Some actions depend on wether this is the load or run memory + /* Some actions depend on whether this is the load or run memory ** area. */ if (S->Run == M) { - /* This is the run (and maybe load) memory area. Handle ** alignment and explict start address and offset. */ @@ -1864,7 +1861,7 @@ unsigned CfgProcess (void) /* If the first segment placed in the memory area needs ** fill bytes for the alignment, emit a warning, since - ** this is somewhat suspicious. + ** that is somewhat suspicious. */ if (M->FillLevel == 0 && NewAddr > Addr) { CfgWarning (GetSourcePos (S->LI), @@ -1876,32 +1873,36 @@ unsigned CfgProcess (void) /* Use the aligned address */ Addr = NewAddr; - } else if (S->Flags & (SF_OFFSET | SF_START)) { + } else if ((S->Flags & (SF_OFFSET | SF_START)) != 0 && + (M->Flags & MF_OVERFLOW) == 0) { /* Give the segment a fixed starting address */ unsigned long NewAddr = S->Addr; + if (S->Flags & SF_OFFSET) { /* An offset was given, no address, make an address */ NewAddr += M->Start; } - if (Addr > NewAddr) { + if (NewAddr < Addr) { /* Offset already too large */ + ++Overflows; if (S->Flags & SF_OFFSET) { - CfgError (GetSourcePos (M->LI), - "Offset too small in `%s', segment `%s'", - GetString (M->Name), - GetString (S->Name)); + CfgWarning (GetSourcePos (S->LI), + "Segment `%s' offset is too small in `%s' by %lu byte%c", + GetString (S->Name), GetString (M->Name), + Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's'); } else { - CfgError (GetSourcePos (M->LI), - "Start address too low in `%s', segment `%s'", - GetString (M->Name), - GetString (S->Name)); + CfgWarning (GetSourcePos (S->LI), + "Segment `%s' start address is too low in `%s' by %lu byte%c", + GetString (S->Name), GetString (M->Name), + Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's'); } + } else { + Addr = NewAddr; } - Addr = NewAddr; } /* Set the start address of this segment, set the readonly flag - ** in the segment and and remember if the segment is in a + ** in the segment, and remember if the segment is in a ** relocatable file or not. */ S->Seg->PC = Addr; @@ -1913,25 +1914,23 @@ unsigned CfgProcess (void) S->Seg->MemArea = M; } else if (S->Load == M) { - - /* This is the load memory area, *and* run and load are + /* This is the load memory area; *and*, run and load are ** different (because of the "else" above). Handle alignment. */ if (S->Flags & SF_ALIGN_LOAD) { /* Align the address */ Addr = AlignAddr (Addr, S->LoadAlignment); } - } - /* If this is the load memory area and the segment doesn't have a + /* If this is the load memory area, and the segment doesn't have a ** fill value defined, use the one from the memory area. */ if (S->Load == M && (S->Flags & SF_FILLVAL) == 0) { S->Seg->FillVal = M->FillVal; } - /* Increment the fill level of the memory area and check for an + /* Increment the fill level of the memory area; and, check for an ** overflow. */ M->FillLevel = Addr + S->Seg->Size - M->Start; @@ -1939,9 +1938,9 @@ unsigned CfgProcess (void) ++Overflows; M->Flags |= MF_OVERFLOW; CfgWarning (GetSourcePos (M->LI), - "Memory area overflow in `%s', segment `%s' (%lu bytes)", - GetString (M->Name), GetString (S->Name), - M->FillLevel - M->Size); + "Segment `%s' overflows memory area `%s' by %lu byte%c", + GetString (S->Name), GetString (M->Name), + M->FillLevel - M->Size, (M->FillLevel - M->Size == 1) ? ' ' : 's'); } /* If requested, define symbols for the start and size of the @@ -1966,10 +1965,9 @@ unsigned CfgProcess (void) ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) { M->F->Size += Addr - StartAddr; } - } - /* If requested, define symbols for start, size and offset of the + /* If requested, define symbols for start, size, and offset of the ** memory area */ if (M->Flags & MF_DEFINE) { @@ -1999,8 +1997,8 @@ unsigned CfgProcess (void) SB_Done (&Buf); } - /* If we didn't have an overflow and are requested to fill the memory - ** area, acount for that in the file size. + /* If we didn't have an overflow, and are requested to fill the memory + ** area, account for that in the file size. */ if ((M->Flags & MF_OVERFLOW) == 0 && (M->Flags & MF_FILL) != 0) { M->F->Size += (M->Size - M->FillLevel); diff --git a/src/ld65/main.c b/src/ld65/main.c index 5030b1dc3..95ed14396 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -819,8 +819,8 @@ int main (int argc, char* argv []) if (MapFileName) { CreateMapFile (SHORT_MAPFILE); } - Error ("Cannot generate output due to memory area overflow%s", - (MemoryAreaOverflows > 1)? "s" : ""); + Error ("Cannot generate most of the files due to memory area overflow%c", + (MemoryAreaOverflows > 1) ? 's' : ' '); } /* Create the output file */ diff --git a/src/sim65/main.c b/src/sim65/main.c index 22f6831e4..dab9b0be8 100644 --- a/src/sim65/main.c +++ b/src/sim65/main.c @@ -156,7 +156,7 @@ static void ReadProgramFile (void) /* Close the file */ fclose (F); - Print (stdout, 1, "Loaded `%s' at $0200-$%04X\n", ProgramFile, Addr - 1); + Print (stderr, 1, "Loaded `%s' at $0200-$%04X\n", ProgramFile, Addr - 1); } @@ -238,7 +238,7 @@ int main (int argc, char* argv[]) ExecuteInsn (); if (MaxCycles && (GetCycles () >= MaxCycles)) { Error ("Maximum number of cycles reached."); - exit (-99); /* do not ues EXIT_FAILURE to avoid conflicts with the + exit (-99); /* do not use EXIT_FAILURE to avoid conflicts with the same value being used in a test program */ } } diff --git a/src/sim65/paravirt.c b/src/sim65/paravirt.c index 0deb59a5f..56211b5c1 100644 --- a/src/sim65/paravirt.c +++ b/src/sim65/paravirt.c @@ -128,7 +128,7 @@ static void PVArgs (CPURegs* Regs) unsigned SP = MemReadZPWord (0x00); unsigned Args = SP - (ArgC + 1) * 2; - Print (stdout, 2, "PVArgs ($%04X)\n", ArgV); + Print (stderr, 2, "PVArgs ($%04X)\n", ArgV); MemWriteWord (ArgV, Args); @@ -155,7 +155,7 @@ static void PVArgs (CPURegs* Regs) static void PVExit (CPURegs* Regs) { - Print (stdout, 1, "PVExit ($%02X)\n", Regs->AC); + Print (stderr, 1, "PVExit ($%02X)\n", Regs->AC); exit (Regs->AC); } @@ -177,7 +177,7 @@ static void PVOpen (CPURegs* Regs) } while (Path[I++]); - Print (stdout, 2, "PVOpen (\"%s\", $%04X)\n", Path, Flags); + Print (stderr, 2, "PVOpen (\"%s\", $%04X)\n", Path, Flags); switch (Flags & 0x03) { case 0x01: @@ -219,7 +219,7 @@ static void PVClose (CPURegs* Regs) unsigned FD = GetAX (Regs); - Print (stdout, 2, "PVClose ($%04X)\n", FD); + Print (stderr, 2, "PVClose ($%04X)\n", FD); RetVal = close (FD); @@ -237,7 +237,7 @@ static void PVRead (CPURegs* Regs) unsigned Buf = PopParam (2); unsigned FD = PopParam (2); - Print (stdout, 2, "PVRead ($%04X, $%04X, $%04X)\n", FD, Buf, Count); + Print (stderr, 2, "PVRead ($%04X, $%04X, $%04X)\n", FD, Buf, Count); Data = xmalloc (Count); @@ -264,7 +264,7 @@ static void PVWrite (CPURegs* Regs) unsigned Buf = PopParam (2); unsigned FD = PopParam (2); - Print (stdout, 2, "PVWrite ($%04X, $%04X, $%04X)\n", FD, Buf, Count); + Print (stderr, 2, "PVWrite ($%04X, $%04X, $%04X)\n", FD, Buf, Count); Data = xmalloc (Count); while (I < Count) { diff --git a/test/Makefile b/test/Makefile index b942cbcdf..1ad86ca98 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,41 +1,43 @@ -# toplevel makefile for the regression tests +# top-level makefile for the regression tests -MAKE := make --no-print-dir +# You can comment this special target when you debug the regression tests. +# Then, make will give you more progress reports. +.SILENT: ifneq ($(shell echo),) - CMD_EXE = 1 + CMD_EXE := 1 endif ifdef CMD_EXE - RM := del /f EXE := .exe - MKDIR = mkdir - RMDIR = rmdir + DEL = -del /f $(subst /,\,$1) + MKDIR = mkdir $(subst /,\,$1) + RMDIR = -rmdir /s /q $(subst /,\,$1) else - RM := rm -f EXE := - MKDIR = mkdir -p - RMDIR = rmdir + DEL = $(RM) $1 + MKDIR = mkdir $1 + RMDIR = $(RM) -r $1 endif WORKDIR := ../testwrk -.PHONY: dotests clean +CC := gcc + +.PHONY: all dotests continue mostly-clean clean all: dotests $(WORKDIR): - @$(MKDIR) $(WORKDIR) + $(call MKDIR,$(WORKDIR)) -$(WORKDIR)/bdiff$(EXE): $(WORKDIR) - @$(CC) -o $(WORKDIR)/bdiff$(EXE) bdiff.c +$(WORKDIR)/bdiff$(EXE): bdiff.c | $(WORKDIR) + $(CC) -O2 -o $@ $< -dotests: $(WORKDIR)/bdiff$(EXE) - @$(MAKE) -C val clean all - @$(MAKE) -C ref clean all - @$(MAKE) -C err clean all - @$(MAKE) -C misc clean all +.NOTPARALLEL: + +dotests: mostly-clean continue continue: $(WORKDIR)/bdiff$(EXE) @$(MAKE) -C val all @@ -43,10 +45,12 @@ continue: $(WORKDIR)/bdiff$(EXE) @$(MAKE) -C err all @$(MAKE) -C misc all -clean: +mostly-clean: @$(MAKE) -C val clean @$(MAKE) -C ref clean @$(MAKE) -C err clean @$(MAKE) -C misc clean - @$(RM) $(WORKDIR)/bdiff$(EXE) - @$(RMDIR) $(WORKDIR) + +clean: mostly-clean + @$(call DEL,$(WORKDIR)/bdiff$(EXE)) + @$(call RMDIR,$(WORKDIR)) diff --git a/test/err/Makefile b/test/err/Makefile index 40ccfcb59..bc4226acb 100644 --- a/test/err/Makefile +++ b/test/err/Makefile @@ -1,52 +1,29 @@ - # makefile for the tests that MUST NOT compile ifneq ($(shell echo),) - CMD_EXE = 1 + CMD_EXE := 1 endif -CC65FLAGS = -t sim6502 - -CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) - ifdef CMD_EXE -RM := del /f + NOT := - # Hack + DEL = -del /f $(subst /,\,$1) else -RM := rm -f + NOT := ! + DEL = $(RM) $1 endif -WORKDIR := ./../../testwrk +CC65 := $(if $(wildcard ../../bin/cc65*),../../bin/cc65,cc65) + +WORKDIR := ../../testwrk .PHONY: all clean -SOURCES := $(wildcard *.c) -TESTS := $(SOURCES:%.c=$(WORKDIR)/%.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.o.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.os.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osi.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osir.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oi.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oir.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.or.prg) +TESTS := $(patsubst %.c,$(WORKDIR)/%.s,$(wildcard *.c)) all: $(TESTS) -$(WORKDIR)/%.prg: %.c - ! $(CL65) $(CC65FLAGS) $< -o $@ -$(WORKDIR)/%.o.prg: %.c - ! $(CL65) -O $(CC65FLAGS) $< -o $@ -$(WORKDIR)/%.os.prg: %.c - ! $(CL65) -Os $(CC65FLAGS) $< -o $@ -$(WORKDIR)/%.osi.prg: %.c - ! $(CL65) -Osi $(CC65FLAGS) $< -o $@ -$(WORKDIR)/%.osir.prg: %.c - ! $(CL65) -Osir $(CC65FLAGS) $< -o $@ -$(WORKDIR)/%.oi.prg: %.c - ! $(CL65) -Oi $(CC65FLAGS) $< -o $@ -$(WORKDIR)/%.oir.prg: %.c - ! $(CL65) -Oir $(CC65FLAGS) $< -o $@ -$(WORKDIR)/%.or.prg: %.c - ! $(CL65) -Or $(CC65FLAGS) $< -o $@ +$(WORKDIR)/%.s: %.c + $(NOT) $(CC65) -o $@ $< + clean: - @$(RM) $(TESTS) - @$(RM) $(SOURCES:%.c=$(WORKDIR)/%.o) + @$(call DEL,$(TESTS)) diff --git a/test/err/cc65091001.c b/test/err/cc65091001.c index 265df0aac..65ce6ec83 100644 --- a/test/err/cc65091001.c +++ b/test/err/cc65091001.c @@ -9,6 +9,7 @@ #include <assert.h> #include <string.h> +#include <stdio.h> typedef unsigned char U8; char var = 0xf0; char fn(char bar) diff --git a/test/err/cc65150311-1.c b/test/err/cc65150311-1.c new file mode 100644 index 000000000..c4a836e39 --- /dev/null +++ b/test/err/cc65150311-1.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + ++p; /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-10.c b/test/err/cc65150311-10.c new file mode 100644 index 000000000..14e14d4fd --- /dev/null +++ b/test/err/cc65150311-10.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = &func - p; /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-11.c b/test/err/cc65150311-11.c new file mode 100644 index 000000000..ffc8c9a02 --- /dev/null +++ b/test/err/cc65150311-11.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = func - p; /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-2.c b/test/err/cc65150311-2.c new file mode 100644 index 000000000..34c862ad8 --- /dev/null +++ b/test/err/cc65150311-2.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = (p > &func); /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-3.c b/test/err/cc65150311-3.c new file mode 100644 index 000000000..2bf8267a5 --- /dev/null +++ b/test/err/cc65150311-3.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = (p > func); /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-4.c b/test/err/cc65150311-4.c new file mode 100644 index 000000000..0a7f44ec0 --- /dev/null +++ b/test/err/cc65150311-4.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = func - func; /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-5.c b/test/err/cc65150311-5.c new file mode 100644 index 000000000..41229ad67 --- /dev/null +++ b/test/err/cc65150311-5.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = func - &func; /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-6.c b/test/err/cc65150311-6.c new file mode 100644 index 000000000..a08ab11d3 --- /dev/null +++ b/test/err/cc65150311-6.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = &func - func; /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-7.c b/test/err/cc65150311-7.c new file mode 100644 index 000000000..71e6368f7 --- /dev/null +++ b/test/err/cc65150311-7.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = &func - &func; /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-8.c b/test/err/cc65150311-8.c new file mode 100644 index 000000000..d18dc0b2d --- /dev/null +++ b/test/err/cc65150311-8.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = p - &func; /* invalid C */ + + return 0; +} diff --git a/test/err/cc65150311-9.c b/test/err/cc65150311-9.c new file mode 100644 index 000000000..8cf805b07 --- /dev/null +++ b/test/err/cc65150311-9.c @@ -0,0 +1,26 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + + n = p - func; /* invalid C */ + + return 0; +} diff --git a/test/err/static-2.c b/test/err/static-2.c new file mode 100644 index 000000000..c89097825 --- /dev/null +++ b/test/err/static-2.c @@ -0,0 +1,20 @@ +/* + !!DESCRIPTION!! global non-static and static conflicts + !!ORIGIN!! cc65 regression tests + !!LICENCE!! Public Domain + !!AUTHOR!! Greg King +*/ + +/* + see: https://github.com/cc65/cc65/issues/191 +*/ + +#pragma warn(error, on) + +int n; +static int n; /* should give an error */ + +int main(void) +{ + return n; +} diff --git a/test/err/static-3.c b/test/err/static-3.c new file mode 100644 index 000000000..5b6839a6a --- /dev/null +++ b/test/err/static-3.c @@ -0,0 +1,20 @@ +/* + !!DESCRIPTION!! global non-static and static conflicts + !!ORIGIN!! cc65 regression tests + !!LICENCE!! Public Domain + !!AUTHOR!! Greg King +*/ + +/* + see: https://github.com/cc65/cc65/issues/191 +*/ + +#pragma warn(error, on) + +extern int n; +static int n; /* should give an error */ + +int main(void) +{ + return n; +} diff --git a/test/err/static-4.c b/test/err/static-4.c new file mode 100644 index 000000000..a2cdeb78a --- /dev/null +++ b/test/err/static-4.c @@ -0,0 +1,20 @@ +/* + !!DESCRIPTION!! global non-static and static conflicts + !!ORIGIN!! cc65 regression tests + !!LICENCE!! Public Domain + !!AUTHOR!! Greg King +*/ + +/* + see: https://github.com/cc65/cc65/issues/191 +*/ + +#pragma warn(error, on) + +static int n; +int n; /* should give an error */ + +int main(void) +{ + return n; +} diff --git a/test/misc/Makefile b/test/misc/Makefile index b18d9165e..918316c6c 100644 --- a/test/misc/Makefile +++ b/test/misc/Makefile @@ -2,66 +2,62 @@ # makefile for the remaining tests that need special care in one way or another ifneq ($(shell echo),) - CMD_EXE = 1 + CMD_EXE := 1 endif -CC65FLAGS = -t sim6502 -SIM65FLAGS = -x 200000000 - -CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) -SIM65 := $(if $(wildcard ../../bin/sim65*),../../bin/sim65,sim65) - ifdef CMD_EXE -RM := del /f + S := $(subst /,\,/) + NOT := - # Hack + DEL = -del /f $(subst /,\,$1) else -RM := rm -f + S := / + NOT := ! + DEL = $(RM) $1 endif -WORKDIR := ./../../testwrk +CC65FLAGS := -t sim6502 +SIM65FLAGS := -x 200000000 +CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) +SIM65 := $(if $(wildcard ../../bin/sim65*),..$S..$Sbin$Ssim65,sim65) + +WORKDIR := ..$S..$Stestwrk DIFF := $(WORKDIR)/bdiff .PHONY: all clean SOURCES := $(wildcard *.c) -TESTS := $(SOURCES:%.c=$(WORKDIR)/%.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.o.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.os.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osi.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osir.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oi.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oir.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.or.prg) - -# FIXME: actually use/build differently optimized programs here +TESTS := $(foreach option,. .o. .os. .osi. .osir. .oi. .oir. .or.,$(SOURCES:%.c=$(WORKDIR)/%$(option)prg)) all: $(TESTS) # should compile, but then hangs in an endless loop $(WORKDIR)/endless%prg: endless.c - $(CL65) $(CC65FLAGS) $< -o $@ - ! $(SIM65) $(SIM65FLAGS) $@ + $(CL65) $(subst .,,$(*:.o%=-O%)) $(CC65FLAGS) $< -o $@ + $(NOT) $(SIM65) $(SIM65FLAGS) $@ -# these need reference data that cant be generated by a host compiled program +# these need reference data that can't be generated by a host-compiled program, # in a useful way $(WORKDIR)/limits%prg: limits.c - $(CL65) $(CC65FLAGS) $< -o $@ + $(CL65) $(subst .,,$(*:.o%=-O%)) $(CC65FLAGS) $< -o $@ $(SIM65) $(SIM65FLAGS) $@ > $(WORKDIR)/limits.out $(DIFF) $(WORKDIR)/limits.out limits.ref # the rest are tests that fail currently for one reason or another $(WORKDIR)/fields%prg: fields.c - @echo "FIXME: " $@ "will currently fail" - $(CL65) $(CC65FLAGS) $< -o $@ + @echo "FIXME: " $@ "currently will fail." + $(CL65) $(subst .,,$(*:.o%=-O%)) $(CC65FLAGS) $< -o $@ -$(SIM65) $(SIM65FLAGS) $@ $(WORKDIR)/sitest%prg: sitest.c - @echo "FIXME: " $@ "will currently fail" - -$(CL65) $(CC65FLAGS) $< -o $@ + @echo "FIXME: " $@ "currently will fail." + -$(CL65) $(subst .,,$(*:.o%=-O%)) $(CC65FLAGS) $< -o $@ +# -$(SIM65) $(SIM65FLAGS) $@ +$(WORKDIR)/cc65141011%prg: cc65141011.c + @echo "FIXME: " $@ "currently can fail." + $(CL65) $(subst .,,$(*:.o%=-O%)) $(CC65FLAGS) $< -o $@ -$(SIM65) $(SIM65FLAGS) $@ clean: - @$(RM) $(TESTS) - @$(RM) $(SOURCES:%.c=$(WORKDIR)/%.o) - @$(RM) $(SOURCES:%.c=$(WORKDIR)/%.out) - - + @$(call DEL,$(TESTS)) + @$(call DEL,$(SOURCES:.c=.o)) + @$(call DEL,$(SOURCES:%.c=$(WORKDIR)/%.out)) diff --git a/test/misc/cc65141011.c b/test/misc/cc65141011.c new file mode 100755 index 000000000..26cef7099 --- /dev/null +++ b/test/misc/cc65141011.c @@ -0,0 +1,59 @@ +/* + !!DESCRIPTION!! equality problem + !!ORIGIN!! Testsuite + !!LICENCE!! Public Domain +*/ + +/* + Different results, depending on whether constant is on left or right side. + + The optimizer sometimes makes code that executes the right-side expression + as eight bits; but then, tests it against the left-side zero as 16 bits. + The high-byte is garbage; therefore, that test might, or might not, work. + It depends on the platform and the amount of optimization. + + http://www.cc65.org/mailarchive/2014-10/11680.html + http://www.cc65.org/mailarchive/2014-10/11682.html + http://www.cc65.org/mailarchive/2014-10/11683.html +*/ + +#include <stdio.h> + +static unsigned char fails = 4; +static unsigned char bad[3], good[3]; + +int main(void) +{ + unsigned char joy_state = 0x7e; + unsigned a, b; + + /* NOTE: It fails in only the printf() statements, the other stuff + below works! */ + printf("bad: %u, ", 0 == (joy_state & 1) ); + printf("good: %u\n", (joy_state & 1) == 0 ); + + sprintf(bad, "%u", 0 == (joy_state & 1) ); + sprintf(good, "%u", (joy_state & 1) == 0 ); + + printf("bad: %u, ", bad[0] - '0' ); + printf("good: %u\n", good[0] - '0' ); + + fails -= bad[0] - '0'; + fails -= good[0] - '0'; + + if (0 == (joy_state & 1)) fails--; + if ((joy_state & 1) == 0) fails--; + + printf("failures: %u\n", fails ); + + /* The above printf() returns a value with a zero high-byte. + ** Therefore, the next (broken) statement works (by accident). + */ + a = 0 == (joy_state & 1); + b = (joy_state & 1) == 0; + + printf("a: %u, ", a ); + printf("b: %u\n", b ); + + return fails; +} diff --git a/test/ref/Makefile b/test/ref/Makefile index b752adc1d..09dd96d44 100644 --- a/test/ref/Makefile +++ b/test/ref/Makefile @@ -3,46 +3,50 @@ # compared with reference output ifneq ($(shell echo),) - CMD_EXE = 1 + CMD_EXE := 1 endif -CC65FLAGS = -t sim6502 -SIM65FLAGS = -x 200000000 - -CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) -SIM65 := $(if $(wildcard ../../bin/sim65*),../../bin/sim65,sim65) - ifdef CMD_EXE -RM := del /f + S := $(subst /,\,/) + DEL = -del /f $(subst /,\,$1) else -RM := rm -f + S := / + DEL = $(RM) $1 endif -WORKDIR := ./../../testwrk +CC65FLAGS := -t sim6502 +SIM65FLAGS := -x 200000000 +CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) +SIM65 := $(if $(wildcard ../../bin/sim65*),..$S..$Sbin$Ssim65,sim65) + +WORKDIR := ..$S..$Stestwrk DIFF := $(WORKDIR)/bdiff +CC := gcc CFLAGS := -O2 -Wall -W -Wextra -fwrapv -fno-strict-overflow .PHONY: all clean -REFS := $(patsubst %.c,$(WORKDIR)/%.ref,$(wildcard *.c)) - SOURCES := $(wildcard *.c) -TESTS := $(SOURCES:%.c=$(WORKDIR)/%.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.o.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.os.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osi.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osir.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oi.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oir.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.or.prg) +REFS := $(SOURCES:%.c=$(WORKDIR)/%.ref) +TESTS := $(foreach option,. .o. .os. .osi. .osir. .oi. .oir. .or.,$(SOURCES:%.c=$(WORKDIR)/%$(option)prg)) all: $(REFS) $(TESTS) $(WORKDIR)/%.ref: %.c $(CC) $(CFLAGS) $< -o $(WORKDIR)/$*.host - $(WORKDIR)/$*.host > $@ + $(WORKDIR)$S$*.host > $@ + +# Some files have "K & R"-style syntax. Therefore, some forward +# function-declarations don't match the later function definitions. +# Those programs fail when fastcall is used; but, the cdecl calling convention +# tolerates those conflicts. Therefore, make their functions default to cdecl. +# +$(WORKDIR)/init%prg: CC65FLAGS += -Wc --all-cdecl +$(WORKDIR)/switch.%rg: CC65FLAGS += -Wc --all-cdecl +$(WORKDIR)/yacc.%rg: CC65FLAGS += -Wc --all-cdecl +$(WORKDIR)/yaccdbg%prg: CC65FLAGS += -Wc --all-cdecl $(WORKDIR)/%.prg: %.c $(WORKDIR)/%.ref $(CL65) $(CC65FLAGS) $< -o $@ @@ -85,8 +89,8 @@ $(WORKDIR)/%.or.prg: %.c $(WORKDIR)/%.ref $(DIFF) $(WORKDIR)/$*.out $(WORKDIR)/$*.ref clean: - @$(RM) $(TESTS) - @$(RM) $(SOURCES:%.c=$(WORKDIR)/%.o) - @$(RM) $(SOURCES:%.c=$(WORKDIR)/%.out) - @$(RM) $(SOURCES:%.c=$(WORKDIR)/%.ref) - @$(RM) $(SOURCES:%.c=$(WORKDIR)/%.host) + @$(call DEL,$(TESTS)) + @$(call DEL,$(SOURCES:.c=.o)) + @$(call DEL,$(SOURCES:%.c=$(WORKDIR)/%.out)) + @$(call DEL,$(SOURCES:%.c=$(WORKDIR)/%.ref)) + @$(call DEL,$(SOURCES:%.c=$(WORKDIR)/%.host)) diff --git a/test/ref/otccex.c b/test/ref/otccex.c index f3d6c71ec..aa5df158f 100644 --- a/test/ref/otccex.c +++ b/test/ref/otccex.c @@ -126,7 +126,7 @@ mymain(int argc,char **argv) } else { /* why not using a function pointer ? */ f = &fact; - print_num((*(long (*)())f)(n), base); + print_num((*(long (*)(int))f)(n), base); } printf("\n"); return 0; diff --git a/test/val/Makefile b/test/val/Makefile index 2e0aca278..4ad8160ef 100644 --- a/test/val/Makefile +++ b/test/val/Makefile @@ -2,37 +2,37 @@ # makefile for the regression tests that return an error code on failure ifneq ($(shell echo),) - CMD_EXE = 1 + CMD_EXE := 1 endif -CC65FLAGS = -t sim6502 -SIM65FLAGS = -x 200000000 +ifdef CMD_EXE + DEL = -del /f $(subst /,\,$1) +else + DEL = $(RM) $1 +endif + +CC65FLAGS := -t sim6502 +SIM65FLAGS := -x 200000000 CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) SIM65 := $(if $(wildcard ../../bin/sim65*),../../bin/sim65,sim65) -ifdef CMD_EXE -RM := del /f -else -RM := rm -f -endif - -WORKDIR := ./../../testwrk +WORKDIR := ../../testwrk .PHONY: all clean SOURCES := $(wildcard *.c) -TESTS := $(SOURCES:%.c=$(WORKDIR)/%.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.o.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.os.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osi.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.osir.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oi.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.oir.prg) -TESTS += $(SOURCES:%.c=$(WORKDIR)/%.or.prg) +TESTS := $(foreach option,. .o. .os. .osi. .osir. .oi. .oir. .or.,$(SOURCES:%.c=$(WORKDIR)/%$(option)prg)) all: $(TESTS) +# Some files have "K & R"-style syntax. Therefore, some forward +# function-declarations don't match the later function definitions. +# Those programs fail when fastcall is used; but, the cdecl calling convention +# tolerates those conflicts. Therefore, make their functions default to cdecl. +# +$(WORKDIR)/cq4%prg $(WORKDIR)/cq71.%rg $(WORKDIR)/cq81%prg $(WORKDIR)/cq84%prg: CC65FLAGS += -Wc --all-cdecl + $(WORKDIR)/%.prg: %.c $(CL65) $(CC65FLAGS) $< -o $@ $(SIM65) $(SIM65FLAGS) $@ @@ -66,5 +66,5 @@ $(WORKDIR)/%.or.prg: %.c $(SIM65) $(SIM65FLAGS) $@ clean: - @$(RM) $(TESTS) - @$(RM) $(SOURCES:%.c=$(WORKDIR)/%.o) + @$(call DEL,$(TESTS)) + @$(call DEL,$(SOURCES:.c=.o)) diff --git a/test/val/add3a.c b/test/val/add3a.c new file mode 100755 index 000000000..4ca32d06b --- /dev/null +++ b/test/val/add3a.c @@ -0,0 +1,73 @@ + +/* + !!DESCRIPTION!! Addition tests - mostly int's + !!ORIGIN!! SDCC regression tests + !!LICENCE!! GPL, read COPYING.GPL +*/ + +#include <stdio.h> +#include <stdlib.h> + +static unsigned int failures = 0; + +/* + this test assumes: + sizeof(long) == 4 + + CAUTION: the wraparound behaviour is actually undefined, to get the "expected" + behaviour with GCC, use -fwrapv or -fno-strict-overflow + + see: https://gcc.gnu.org/wiki/FAQ#signed_overflow +*/ + +#ifdef REFERENCE + +/* + make sure the reference output uses types with + proper size +*/ + +#include <stdint.h> + +int32_t long0 = 0; + +#else + +long long0 = 0; + +#endif + +void print(void) +{ +#if defined(REFERENCE) && defined(REFCC_SIZEOF_LONG_64BIT) + printf("long0: %d\n", long0); +#else + printf("long0: %ld\n", long0); +#endif +} + +int main(void) +{ + long0 = 0x7f000000L; + /* wrap around zero */ + print(); + long0 = long0 + 0x2000000L; + if(long0 != -0x7f000000L) { + printf("failed!\n"); + failures++; + } + print(); + + long0 = 0x7f000000L; + /* wrap around zero */ + print(); + long0 = long0 + 0x2000000L; + print(); + if(long0 != -0x7f000000L) { + printf("failed!\n"); + failures++; + } + print(); + + return failures; +} diff --git a/test/val/add5.c b/test/val/add5.c new file mode 100644 index 000000000..f8b7d669c --- /dev/null +++ b/test/val/add5.c @@ -0,0 +1,250 @@ +/* +** !!DESCRIPTION!! Simple tests about adding pointers and offsets +** !!ORIGIN!! cc65 regression tests +** !!LICENCE!! Public Domain +** !!AUTHOR!! 2016-01-01, Greg King +*/ + +#include <stdio.h> + +static unsigned char failures = 0; + +static char array[16]; + +static char *cPtr; +static int *iPtr; +static long *lPtr; + +/* These functions test: adding an offset variable to a pointer variable. */ + +static void cPointer_char(void) +{ + char *cP = array; + char offset = 3; + + cPtr = cP + offset; + if (cPtr != (void *)&array[3]) { + ++failures; + } +} + +static void cPointer_int(void) +{ + char *cP = array; + int offset = 3; + + cPtr = cP + offset; + if (cPtr != (void *)&array[3]) { + ++failures; + } +} + +static void cPointer_long(void) +{ + char *cP = array; + long offset = 3; + + cPtr = cP + offset; + if (cPtr != (void *)&array[3]) { + ++failures; + } +} + +static void iPointer_char(void) +{ + int *iP = (int *)array; + char offset = 3; + + iPtr = iP + offset; + if (iPtr != (void *)&array[6]) { + ++failures; + } +} + +static void iPointer_int(void) +{ + int *iP = (int *)array; + int offset = 3; + + iPtr = iP + offset; + if (iPtr != (void *)&array[6]) { + ++failures; + } +} + +static void iPointer_long(void) +{ + int *iP = (int *)array; + long offset = 3; + + iPtr = iP + offset; + if (iPtr != (void *)&array[6]) { + ++failures; + } +} + +static void lPointer_char(void) +{ + long *lP = (long *)array; + char offset = 3; + + lPtr = lP + offset; + if (lPtr != (void *)&array[12]) { + ++failures; + } +} + +static void lPointer_int(void) +{ + long *lP = (long *)array; + int offset = 3; + + lPtr = lP + offset; + if (lPtr != (void *)&array[12]) { + ++failures; + } +} + +static void lPointer_long(void) +{ + long *lP = (long *)array; + long offset = 3; + + lPtr = lP + offset; + if (lPtr != (void *)&array[12]) { + ++failures; + } +} + +/* These functions test: adding a pointer variable to an offset variable. */ + +static void char_cPointer(void) +{ + char *cP = array; + char offset = 3; + + cPtr = offset + cP; + if (cPtr != (void *)&array[3]) { + ++failures; + } +} + +static void int_cPointer(void) +{ + char *cP = array; + int offset = 3; + + cPtr = offset + cP; + if (cPtr != (void *)&array[3]) { + ++failures; + } +} + +static void long_cPointer(void) +{ + char *cP = array; + long offset = 3; + + cPtr = (offset + cP); + if (cPtr != (void *)&array[3]) { + ++failures; + } +} + +static void char_iPointer(void) +{ + int *iP = (int *)array; + char offset = 3; + + iPtr = offset + iP; + if (iPtr != (void *)&array[6]) { + ++failures; + } +} + +static void int_iPointer(void) +{ + int *iP = (int *)array; + int offset = 3; + + iPtr = offset + iP; + if (iPtr != (void *)&array[6]) { + ++failures; + } +} + +static void long_iPointer(void) +{ + int *iP = (int *)array; + long offset = 3; + + iPtr = (offset + iP); + if (iPtr != (void *)&array[6]) { + ++failures; + } +} + +static void char_lPointer(void) +{ + long *lP = (long *)array; + char offset = 3; + + lPtr = offset + lP; + if (lPtr != (void *)&array[12]) { + ++failures; + } +} + +static void int_lPointer(void) +{ + long *lP = (long *)array; + int offset = 3; + + lPtr = offset + lP; + if (lPtr != (void *)&array[12]) { + ++failures; + } +} + +static void long_lPointer(void) +{ + long *lP = (long *)array; + long offset = 3; + + lPtr = (offset + lP); + if (lPtr != (void *)&array[12]) { + ++failures; + } +} + +int main(void) +{ + cPointer_char(); + cPointer_int(); + cPointer_long(); + + iPointer_char(); + iPointer_int(); + iPointer_long(); + + lPointer_char(); + lPointer_int(); + lPointer_long(); + + char_cPointer(); + int_cPointer(); + long_cPointer(); + + char_iPointer(); + int_iPointer(); + long_iPointer(); + + char_lPointer(); + int_lPointer(); + long_lPointer(); + + if (failures != 0) { + printf("add5: failures: %u\n", failures); + } + return failures; +} diff --git a/test/val/casttochar.c b/test/val/casttochar.c new file mode 100755 index 000000000..d492f6bb8 --- /dev/null +++ b/test/val/casttochar.c @@ -0,0 +1,49 @@ + +/* + !!DESCRIPTION!! Cast to char + !!ORIGIN!! Piotr Fusik + !!LICENCE!! PD +*/ + +#include <stdio.h> +#include <stdlib.h> + +static unsigned int failures = 0; + +int f1(int i, int j) { + return (signed char) (i + 1) == j; +} + +int f2(int i, int j) { + return (unsigned char) (i + 1) == j; +} + +int f3(int i, int j) { + return (char) (i + 1) == j; +} + +int main(void) +{ + printf("f1: got :%04x ", f1(0x1234, 0x35)); + if(f1(0x1234, 0x35) == 0) { + printf("- failed"); + failures++; + } + printf("\n"); + + printf("f2: got :%04x ", f2(0x1234, 0x35)); + if(f2(0x1234, 0x35) == 0) { + printf("- failed"); + failures++; + } + printf("\n"); + + printf("f3: got :%04x ", f3(0x1234, 0x35)); + if(f3(0x1234, 0x35) == 0) { + printf("- failed"); + failures++; + } + printf("\n"); + + return failures; +} diff --git a/test/val/cc65141002.c b/test/val/cc65141002.c new file mode 100755 index 000000000..ae5cd3d5f --- /dev/null +++ b/test/val/cc65141002.c @@ -0,0 +1,45 @@ + +/* + !!DESCRIPTION!! forgetting to emit labels + !!ORIGIN!! Testsuite + !!LICENCE!! Public Domain +*/ + +/* + http://www.cc65.org/mailarchive/2014-10/11673.html + http://www.cc65.org/mailarchive/2014-10/11675.html +*/ + +#include <stdlib.h> +#include <stdio.h> + +struct udata { + int (*u_sigvec[16])(); + int u_argn; + int u_argn1; +}; + +struct udata udata; + +#define sig (int)udata.u_argn +#define func (int (*)())udata.u_argn1 + +int _signal(void) +{ + if (func != 0) { + goto nogood; + } + udata.u_sigvec[sig] = func; + return 0; + +nogood: + return (-1); +} + +int main(int n,char **args) +{ + _signal(); + printf("it works\n"); + + return 0; +} diff --git a/test/val/cc65141022.c b/test/val/cc65141022.c new file mode 100755 index 000000000..1d7792cf2 --- /dev/null +++ b/test/val/cc65141022.c @@ -0,0 +1,57 @@ + +/* + !!DESCRIPTION!! struct base address dereferencing bug + !!ORIGIN!! Testsuite + !!LICENCE!! Public Domain +*/ + +#include <stdlib.h> +#include <stdio.h> + +struct yywork +{ + char verify, advance; +} yycrank[] = +{ + {0,0} +}; + +struct yysvf +{ + struct yywork *yystoff; +} yysvec[1]; + +unsigned char fails = 0; + +int main(int n, char **args) +{ + struct yysvf *yystate = yysvec; + struct yywork *yyt; + + yystate->yystoff = yycrank; + yyt = yystate->yystoff; + + if(yyt == yycrank) { + printf("yyt == yycrank (ok)\n"); + } else { + printf("yyt != yycrank (fail)\n"); + ++fails; + } + + if(yyt == yystate->yystoff) { + printf("yyt == yystate->yystoff (ok)\n"); + } else { + printf("yyt != yystate->yystoff (fail)\n"); + ++fails; + } + + if(yycrank == yystate->yystoff) { + printf("yycrank == yystate->yystoff (ok)\n"); + } else { + printf("yycrank != yystate->yystoff (fail)\n"); + ++fails; + } + + printf("fails: %d\n", fails); + return fails; +} diff --git a/test/val/cc65150311.c b/test/val/cc65150311.c new file mode 100644 index 000000000..cd644f491 --- /dev/null +++ b/test/val/cc65150311.c @@ -0,0 +1,38 @@ +/* + !!DESCRIPTION!! function pointer bugs + !!ORIGIN!! testsuite + !!LICENCE!! Public Domain + !!AUTHOR!! Greg +*/ + +/* + see: http://www.cc65.org/mailarchive/2015-03/11726.html + and: http://www.cc65.org/mailarchive/2015-03/11734.html +*/ + +static int func(void) {return 0;} +static int (*p)(void); +static int n; + +int main(void) { + + p = func; + n = (p == &func); + n = (p == func); + +/* the following are not valid C and should go into seperate tests that MUST fail */ +/* + ++p; + n = (p > &func); + n = (p > func); + n = func - func; + n = func - &func; + n = &func - func; + n = &func - &func; + n = p - &func; + n = p - func; + n = &func - p; + n = func - p; +*/ + return 0; +} diff --git a/test/val/pointed-array.c b/test/val/pointed-array.c new file mode 100644 index 000000000..3390ac94b --- /dev/null +++ b/test/val/pointed-array.c @@ -0,0 +1,91 @@ +/* +** !!DESCRIPTION!! Simple tests of pointer-to-array dereferences +** !!ORIGIN!! cc65 regression tests +** !!LICENCE!! Public Domain +** !!AUTHOR!! 2015-06-29, Greg King +*/ + +#include <stdio.h> + +static unsigned char failures = 0; +static size_t Size; + +typedef unsigned char array_t[4][4]; + +static array_t table = { + {12, 13, 14, 15}, + { 8, 9, 10, 11}, + { 4, 5, 6, 7}, + { 0, 1, 2, 3} +}; +static array_t *tablePtr = &table; + +static unsigned (*vector)[2]; + +static unsigned char y = 0, x; + +int main(void) +{ + /* The indirection must convert the expression-type (from Pointer into + ** Array); but, it must not convert the value, because it already points + ** to the start of the array. + */ + /* (Note: I reduce output clutter by using a variable to prevent + ** compiler warnings about constant comparisons and unreachable code. + */ + if ((Size = sizeof *tablePtr) != sizeof table) { + ++failures; + } + if (*tablePtr != table) { + ++failures; + } + + /* Test fetching. */ + do { + x = 0; + do { + if ((*tablePtr)[y][x] != table[y][x]) { + ++failures; + printf("(*tableptr)[%u][%u] (%u) != table[%u][%u] (%u).\n", + y, x, (*tablePtr)[y][x], + y, x, table[y][x]); + } + } while (++x < sizeof table[0]); + } while (++y < sizeof table / sizeof table[0]); + + vector = (unsigned (*)[])table[1]; + if ((*vector)[1] != 0x0B0A) { + ++failures; + } + + /* Test storing. */ + (*tablePtr)[2][1] = 42; + if (table[2][1] != 42) { + ++failures; + printf("table[2][1] == %u (should have changed from 5 to 42).\n", + table[2][1]); + } + x = 3; + y = 1; + (*tablePtr)[y][x] = 83; + if (table[1][3] != 83) { + ++failures; + printf("table[y][x] == %u (should have changed from 11 to 83).\n", + table[1][3]); + } + + /* Test triple indirection. It should compile to two indirection + ** operations. + */ + --***tablePtr; + if (**table != 11) { + ++failures; + printf("**table == %u (should have changed from 12 to 11).\n", + table[0][0]); + } + + if (failures != 0) { + printf("failures: %u\n", failures); + } + return failures; +} diff --git a/test/val/ptrfunc.c b/test/val/ptrfunc.c index e1682507a..55503e176 100644 --- a/test/val/ptrfunc.c +++ b/test/val/ptrfunc.c @@ -5,7 +5,8 @@ */ #include <stdio.h> -#include <limits.h> + +#define NO_IMPLICIT_FUNCPTR_CONV unsigned char success=0; unsigned char failures=0; diff --git a/test/val/rotate8.c b/test/val/rotate8.c new file mode 100644 index 000000000..0cd691c08 --- /dev/null +++ b/test/val/rotate8.c @@ -0,0 +1,156 @@ +/* + !!DESCRIPTION!! Optimized-shift signed ints right by a constant; and, assign to chars. + !!ORIGIN!! cc65 regression tests + !!LICENCE!! Public Domain + !!AUTHOR!! Greg King +*/ + +#include <stdio.h> + +static unsigned char failures = 0; +static unsigned char n = 0; + +/* This number must be read from a variable because +** we want this program, not cc65, to do the shift. +*/ +static const signed int aint0 = 0xAAC0; + +static signed char achar0, achar1; + +static void check(void) +{ + if ((unsigned char)achar0 != (unsigned char)achar1) + ++failures; +} + +static void shift_right_0(void) +{ + achar0 = aint0 >> 0; + check(); +} + +static void shift_right_1(void) +{ + achar0 = aint0 >> 1; + check(); +} + +static void shift_right_2(void) +{ + achar0 = aint0 >> 2; + check(); +} + +static void shift_right_3(void) +{ + achar0 = aint0 >> 3; + check(); +} + +static void shift_right_4(void) +{ + achar0 = aint0 >> 4; + check(); +} + +static void shift_right_5(void) +{ + achar0 = aint0 >> 5; + check(); +} + +static void shift_right_6(void) +{ + achar0 = aint0 >> 6; + check(); +} + +static void shift_right_7(void) +{ + achar0 = aint0 >> 7; + check(); +} + +static void shift_right_8(void) +{ + achar0 = aint0 >> 8; + check(); +} + +static void shift_right_9(void) +{ + achar0 = aint0 >> 9; + check(); +} + +static void shift_right_10(void) +{ + achar0 = aint0 >> 10; + check(); +} + +static void shift_right_11(void) +{ + achar0 = aint0 >> 11; + check(); +} + +static void shift_right_12(void) +{ + achar0 = aint0 >> 12; + check(); +} + +static void shift_right_13(void) +{ + achar0 = aint0 >> 13; + check(); +} + +static void shift_right_14(void) +{ + achar0 = aint0 >> 14; + check(); +} + +static void shift_right_15(void) +{ + achar0 = aint0 >> 15; + check(); +} + +const struct { + signed char achar; + void (*func)(void); +} tests[] = { + {0xC0, shift_right_0}, + {0x60, shift_right_1}, + {0xB0, shift_right_2}, + {0x58, shift_right_3}, + {0xAC, shift_right_4}, + {0x56, shift_right_5}, + {0xAB, shift_right_6}, + {0x55, shift_right_7}, + {0xAA, shift_right_8}, + {0xD5, shift_right_9}, + {0xEA, shift_right_10}, + {0xF5, shift_right_11}, + {0xFA, shift_right_12}, + {0xFD, shift_right_13}, + {0xFE, shift_right_14}, + {0xFF, shift_right_15} +}; + +int main(void) +{ + do { + achar1 = tests[n].achar; + tests[n].func(); + } while (++n < sizeof tests / sizeof tests[0]); + + if (failures) { + printf("rotate8: failures: %u (of %u).\n", + failures, sizeof tests / sizeof tests[0]); + } + return failures; +} diff --git a/test/val/static-1.c b/test/val/static-1.c new file mode 100644 index 000000000..ae2ba6289 --- /dev/null +++ b/test/val/static-1.c @@ -0,0 +1,20 @@ +/* + !!DESCRIPTION!! global non-static and static conflicts + !!ORIGIN!! cc65 regression tests + !!LICENCE!! Public Domain + !!AUTHOR!! Greg King +*/ + +/* + see: https://github.com/cc65/cc65/issues/191 +*/ + +#pragma warn(error, on) + +static int n = 0; +extern int n; /* should not give an error */ + +int main(void) +{ + return n; +} diff --git a/testcode/assembler/paramcount.s b/testcode/assembler/paramcount.s new file mode 100644 index 000000000..4e9190df6 --- /dev/null +++ b/testcode/assembler/paramcount.s @@ -0,0 +1,20 @@ +; Test ca65's handling of the .paramcount read-only variable. +; .paramcount should see all given arguments, even when they are empty. + +.macro push r1, r2, r3, r4, r5, r6 + .out .sprintf(" .paramcount = %u", .paramcount) +.if .paramcount <> 0 +.ifblank r1 + .warning "r1 is blank!" +.exitmacro +.endif + lda r1 + pha + + push r2, r3, r4, r5, r6 +.endif +.endmacro + + push 1, , {} + push 1, , + push 1 diff --git a/testcode/lib/.gitignore b/testcode/lib/.gitignore new file mode 100644 index 000000000..9bb8eaa3e --- /dev/null +++ b/testcode/lib/.gitignore @@ -0,0 +1,2 @@ +*.o +em-test-* diff --git a/testcode/lib/conio.c b/testcode/lib/conio.c new file mode 100644 index 000000000..bdee12262 --- /dev/null +++ b/testcode/lib/conio.c @@ -0,0 +1,137 @@ +/* + * conio api test program + * + * keys: + * + * 1...0 change text color + * F5/F6 change border color + * F7/F8 change background color + * + */ + + +#include <conio.h> +#include <string.h> +#include <stdlib.h> +#include <joystick.h> + +static char grid[5][5] = { + { CH_ULCORNER, CH_HLINE, CH_TTEE, CH_HLINE, CH_URCORNER }, + { CH_VLINE, ' ', CH_VLINE, ' ', CH_VLINE }, + { CH_LTEE, CH_HLINE, CH_CROSS, CH_HLINE, CH_RTEE }, + { CH_VLINE, ' ', CH_VLINE, ' ', CH_VLINE }, + { CH_LLCORNER, CH_HLINE, CH_BTEE, CH_HLINE, CH_LRCORNER }, +}; + +void main(void) +{ + int i, j, n; + unsigned char xsize, ysize, tcol, bgcol, bcol, inpos = 0; + + clrscr(); + screensize(&xsize, &ysize); + cputs("cc65 conio test\n\rInput: [ ]"); + + cputsxy(0, 2, "Colors:" ); + tcol = textcolor(0); /* remember original textcolor */ + bgcol = bgcolor(0); /* remember original background color */ + bcol = bordercolor(0); /* remember original border color */ + bgcolor(bgcol);bordercolor(bcol); + for (i = 0; i < 3; ++i) { + gotoxy(i,3 + i); + for (j = 0; j < 16; ++j) { + textcolor(j); + cputc('X'); + } + } + textcolor(tcol); + + cprintf("\n\n\r Screensize is: %dx%d", xsize, ysize); + + chlinexy(0,6,xsize); + cvlinexy(0,6,3); + chlinexy(0,8,xsize); + cvlinexy(xsize-1,6,3); + cputcxy(0,6,CH_ULCORNER); + cputcxy(xsize-1,6,CH_URCORNER); + cputcxy(0,8,CH_LLCORNER); + cputcxy(xsize-1,8,CH_LRCORNER); + + for (i = 0; i < 5; ++i) { + gotoxy(xsize - 5,i); + for (j = 0; j < 5; ++j) { + cputc(grid[i][j]); + } + } + + gotoxy(0,ysize - 2 - ((256 + xsize) / xsize)); + revers(1); + for (i = 0; i < xsize; ++i) { + cputc('0' + i % 10); + } + revers(0); + for (i = 0; i < 256; ++i) { + if ((i != '\n') && (i != '\r')) { + cputc(i); + } else { + cputc(' '); + } + } + while(wherex() > 0) { + cputc('#'); + } + revers(1); + for (i = 0; i < xsize; ++i) { + cputc('0' + i % 10); + } + revers(0); + + cursor(1); + for (;;) { + + gotoxy(8, 2); + j = n & 1; + revers(j); + cputc(j ? 'R' : ' '); + revers(j ^ 1); + cputs(" revers"); + revers(0); + +#if defined(__NES__) || defined(__PCE__) + + joy_install(joy_static_stddrv); + while (!joy_read(JOY_1)) ; + joy_uninstall(); + +#else + + gotoxy(8 + inpos,1); + i = cgetc(); + if ((i >= '0') && (i<='9')) { + textcolor(i - '0'); + } else if (i == CH_CURS_LEFT) { + inpos = (inpos - 1) & 7; + } else if (i == CH_CURS_RIGHT) { + inpos = (inpos + 1) & 7; + } else if (i == CH_F5) { + bgcol = (bgcol + 1) & 0x0f; + bordercolor(bgcol); + } else if (i == CH_F6) { + bgcol = (bgcol - 1) & 0x0f; + bordercolor(bgcol); + } else if (i == CH_F7) { + bgcol = (bgcol + 1) & 0x0f; + bgcolor(bgcol); + } else if (i == CH_F8) { + bgcol = (bgcol - 1) & 0x0f; + bgcolor(bgcol); + } else { + cputc(i); + inpos = (inpos + 1) & 7; + } + +#endif + + ++n; + } +} diff --git a/testcode/lib/em-test.c b/testcode/lib/em-test.c index bd4eddc6a..f4a56029a 100644 --- a/testcode/lib/em-test.c +++ b/testcode/lib/em-test.c @@ -5,35 +5,9 @@ #include <conio.h> #include <em.h> - -#if defined(__C64__) -#define DRIVERNAME "c64-ram.emd" -#elif defined(__C128__) -#define DRIVERNAME "c128-ram.emd" -#elif defined(__C16__) -#define DRIVERNAME "c16-ram.emd" -#elif defined(__CBM510__) -#define DRIVERNAME "cbm510-ram.emd" -#elif defined(__CBM610__) -#define DRIVERNAME "cbm610-ram.emd" -#elif defined(__APPLE2ENH__) -#define DRIVERNAME "a2e.auxmem.emd" -#elif defined(__APPLE2__) -#define DRIVERNAME "a2.auxmem.emd" -#elif defined(__ATARIXL__) -#define DRIVERNAME "atrx130.emd" -#elif defined(__ATARI__) -#define DRIVERNAME "atr130.emd" -#else -#define DRIVERNAME "unknown" -#error "Unknown target system" -#endif - - #define FORCE_ERROR1 0 #define FORCE_ERROR2 0 - #define PAGE_SIZE 128 /* Size in words */ #define BUF_SIZE (PAGE_SIZE + PAGE_SIZE/2) static unsigned buf[BUF_SIZE]; @@ -75,7 +49,65 @@ static void cmp (unsigned page, register const unsigned* buf, } } +typedef struct emd_test_s { + char key; + char *displayname; + char *drivername; +} emd_test_t; +static emd_test_t drivers[] = { + +#if defined(__APPLE2__) + { '0', "Apple II auxiliary memory", "a2.auxmem.emd" }, +#endif + +#if defined(__APPLE2ENH__) + { '0', "Apple II auxiliary memory", "a2e.auxmem.emd" }, +#endif + +#if defined(__ATARI__) + { '0', "Atari 130XE memory", "atr130.emd" }, +#endif + +#if defined(__ATARIXL__) + { '0', "Atari 130XE memory", "atrx130.emd" }, +#endif + +#if defined(__C16__) + { '0', "C16 RAM above $8000", "c16-ram.emd" }, +#endif + +#if defined(__C64__) + { '0', "C64 RAM above $D000", "c64-ram.emd" }, + { '1', "C64 256K", "c64-c256k.emd" }, + { '2', "Double Quick Brown Box", "c64-dqbb.emd" }, + { '3', "GEORAM", "c64-georam.emd" }, + { '4', "Isepic", "c64-isepic.emd" }, + { '5', "RamCart", "c64-ramcart.emd" }, + { '6', "REU", "c64-reu.emd" }, + { '7', "C128 VDC (in C64 mode)", "c64-vdc.emd" }, + { '8', "C64DTV himem", "dtv-himem.emd" }, +#endif + +#if defined(__C128__) + { '0', "C128 RAM in bank 1", "c128-ram.emd" }, + { '1', "C128 RAM in banks 1, 2 & 3", "c128-ram2.emd" }, + { '2', "GEORAM", "c128-georam.emd" }, + { '3', "RamCart", "c128-ramcart.emd" }, + { '4', "REU", "c128-reu.emd" }, + { '5', "VDC", "c128-vdc.emd" }, +#endif + +#if defined(__CBM510__) + { '0', "CBM5x0 RAM in bank 2", "cbm510-ram.emd" }, +#endif + +#if defined(__CBM610__) + { '0', "CBM6x0/7x0 RAM in bank 2", "cbm610-ram.emd" }, +#endif + + { 0, NULL, NULL } +}; int main (void) { @@ -85,9 +117,27 @@ int main (void) unsigned PageCount; unsigned char X, Y; struct em_copy c; + unsigned index; + signed char valid_key = -1; + char key; clrscr (); - Res = em_load_driver (DRIVERNAME); + cputs ("Which RAM exp to test?\r\n\r\n"); + for (index = 0; drivers[index].key; ++index) { + cprintf("%c: %s\r\n", drivers[index].key, drivers[index].displayname); + } + + while (valid_key < 0) { + key = cgetc(); + for (index = 0; drivers[index].key && valid_key < 0; ++index) { + if (key == drivers[index].key) { + valid_key = index; + } + } + } + + clrscr (); + Res = em_load_driver (drivers[valid_key].drivername); if (Res != EM_ERR_OK) { cprintf ("Error in em_load_driver: %u\r\n", Res); cprintf ("os: %u, %s\r\n", _oserror, _stroserror (_oserror)); diff --git a/testcode/lib/pce/Makefile b/testcode/lib/pce/Makefile new file mode 100644 index 000000000..9a4dd7506 --- /dev/null +++ b/testcode/lib/pce/Makefile @@ -0,0 +1,12 @@ +.PHONY: all clean test + +all: conio.pce + +conio.pce: conio.c + ../../../bin/cl65 -t pce conio.c --mapfile conio.map -o conio.pce + +clean: + $(RM) conio.o conio.pce conio.map + +test: conio.pce + mednafen -force_module pce conio.pce diff --git a/testcode/lib/pce/conio.c b/testcode/lib/pce/conio.c new file mode 100644 index 000000000..a4bd63b15 --- /dev/null +++ b/testcode/lib/pce/conio.c @@ -0,0 +1,129 @@ +#include <conio.h> +#include <time.h> +#include <joystick.h> +#include <string.h> +#include <stdlib.h> + +static int datavar = 10; + +void main(void) +{ + int stackvar = 42; + int i, j; + clock_t clk; + char* p; + unsigned char xsize, ysize, n, nn; + + joy_install(&joy_static_stddrv); + + clrscr(); + screensize(&xsize, &ysize); + + cputs("hello world"); + cputsxy(0, 2, "colors:" ); + for (i = 0; i < 16; ++i) { + textcolor(i); + cputc('X'); + } + textcolor(1); + + gotoxy(0,4); + cprintf("datavar: %02x\n\r", datavar); + cprintf("stackvar: %02x\n\r", stackvar); + + j = joy_count(); + gotoxy(0,9); + cprintf("Found %d Joysticks.", j); + + for (i = 0; i < 4; ++i) { + gotoxy(0, 16 + i); + p = malloc(16); + memcpy(p, "0123456789abcdef", 16); + cprintf("alloc'ed at: %04p - %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", p, + p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7], + p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15] + ); + } + memcpy(p, main, 0); /* test that a zero length doesn't copy 64K */ + + gotoxy(0,ysize - 1); + for (i = 0; i < xsize; ++i) { + cputc('0' + i % 10); + } + + gotoxy(0,ysize - 2 - ((256 + xsize) / xsize)); + for (i = 0; i < xsize; ++i) { + cputc('0' + i % 10); + } + for (i = 0; i < (xsize * 5); ++i) { + cputc('#'); + } + gotoxy(0,ysize - 1 - ((256 + xsize) / xsize)); + for (i = 0; i < 256; ++i) { + if ((i != '\n') && (i != '\r')) { + cputc(i); + } + } + + i = get_tv(); + gotoxy(30,0); + cputs("TV Mode: "); + switch(i) { + case TV_NTSC: + cputs("NTSC"); + break; + case TV_PAL: + cputs("PAL"); + break; + case TV_OTHER: + cputs("OTHER"); + break; + } + cprintf(" %dx%d", xsize, ysize); + + for(;;) { + gotoxy(13,4); + cprintf("%02x", datavar); + gotoxy(13,5); + cprintf("%02x", stackvar); + ++datavar; ++stackvar; + + gotoxy(0,7); + clk = clock(); + cprintf("clock: %08lx", clk); + + for (i = 0; i < 4; ++i) { + gotoxy(0, 11 + i); + j = joy_read (i); + cprintf ("pad %d: %02x %-6s%-6s%-6s%-6s%-6s%-6s%-6s%-6s", + i, j, + (j & joy_masks[JOY_UP])? " up " : " ---- ", + (j & joy_masks[JOY_DOWN])? " down " : " ---- ", + (j & joy_masks[JOY_LEFT])? " left " : " ---- ", + (j & joy_masks[JOY_RIGHT])? "right " : " ---- ", + (j & joy_masks[JOY_FIRE])? " fire " : " ---- ", + (j & joy_masks[JOY_FIRE2])? "fire2 " : " ---- ", + (j & joy_masks[JOY_SELECT])? "select" : " ---- ", + (j & joy_masks[JOY_RUN])? " run " : " ---- "); + } + + gotoxy(xsize - 10, 3); + nn = (n >> 5) & 1; + revers(nn); + cputc(nn ? 'R' : ' '); + cputs(" revers"); + revers(0); + + if ((n & 0x1f) == 0x00) { + nn = p[15]; + ((char*)memmove(p + 1, p, 15))[-1] = nn; + gotoxy(22, 19); + cprintf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", + p[0],p[1],p[ 2],p[ 3],p[ 4],p[ 5],p[ 6],p[ 7], + p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]); + } + + waitvblank(); + ++n; + } +} diff --git a/testcode/lib/snprintf-test.c b/testcode/lib/snprintf-test.c new file mode 100644 index 000000000..d3af47d78 --- /dev/null +++ b/testcode/lib/snprintf-test.c @@ -0,0 +1,144 @@ +/* +** Test a function that formats and writes characters into a string buffer. +** This program does not test formatting. It tests some behaviors that are +** specific to the buffer. It tests that certain conditions are handled +** properly. +** +** 2015-07-17, Greg King +*/ + +#include <conio.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +static const char format[] = "1234567890\nabcdefghijklmnopqrstuvwxyz\n%u\n%s\n\n"; +#define FORMAT_SIZE (sizeof format - 2u - 2u - 1u) + +#define arg1 12345u +#define ARG1_SIZE (5u) + +static const char arg2[] = "!@#$%^&*()-+"; +#define ARG2_SIZE (sizeof arg2 - 1u) + +#define STRING_SIZE (FORMAT_SIZE + ARG1_SIZE + ARG2_SIZE) + +static char buf[256]; +static int size; + + +static void fillbuf(void) +{ + memset(buf, 0xFF, sizeof buf - 1u); + buf[sizeof buf - 1u] = '\0'; +} + + +unsigned char main(void) +{ + static unsigned char failures = 0; + + /* Show what sprintf() should create. */ + + if ((size = printf(format, arg1, arg2)) != STRING_SIZE) { + ++failures; + printf("printf() gave the wrong size: %d.\n", size); + } + + /* Test the normal behavior of sprintf(). */ + + fillbuf(); + size = sprintf(buf, format, arg1, arg2); + fputs(buf, stdout); + if (size != STRING_SIZE) { + ++failures; + printf("sprintf() gave the wrong size: %d.\n", size); + } + + /* Test the normal behavior of snprintf(). */ + + fillbuf(); + size = snprintf(buf, sizeof buf, format, arg1, arg2); + fputs(buf, stdout); + if (size != STRING_SIZE) { + ++failures; + printf("snprintf(sizeof buf) gave the wrong size:\n %d.\n", size); + } + + /* Does snprintf() return the full-formatted size even when the buffer + ** is short? Does it write beyond the end of that buffer? + */ + + fillbuf(); + size = snprintf(buf, STRING_SIZE - 5u, format, arg1, arg2); + if (size != STRING_SIZE) { + ++failures; + printf("snprintf(STRING_SIZE-5) gave the wrong size:\n %d.\n", size); + } + if (buf[STRING_SIZE - 5u - 1u] != '\0' || buf[STRING_SIZE - 5u] != 0xFF) { + ++failures; + printf("snprintf(STRING_SIZE-5) wrote beyond\n the end of the buffer.\n"); + } + + /* Does snprintf() detect a buffer size that is too big? */ + + fillbuf(); + errno = 0; + size = snprintf(buf, 0x8000, format, arg1, arg2); + if (size >= 0) { + ++failures; + printf("snprintf(0x8000) didn't give an error:\n %d; errno=%d.\n", size, errno); + } else { + printf("snprintf(0x8000) did give an error:\n errno=%d.\n", errno); + } + if (buf[0] != 0xFF) { + ++failures; + printf("snprintf(0x8000) wrote into the buffer.\n"); + } + + /* snprintf() must measure the length of the formatted output even when the + ** buffer size is zero. But, it must not touch the buffer. + */ + + fillbuf(); + size = snprintf(buf, 0, format, arg1, arg2); + if (size != STRING_SIZE) { + ++failures; + printf("snprintf(0) gave the wrong size:\n %d.\n", size); + } + if (buf[0] != 0xFF) { + ++failures; + printf("snprintf(0) wrote into the buffer.\n"); + } + + /* Does sprintf() detect a zero buffer-pointer? */ + + errno = 0; + size = sprintf(NULL, format, arg1, arg2); + if (size >= 0) { + ++failures; + printf("sprintf(NULL) didn't give an error:\n %d; errno=%d.\n", size, errno); + } else { + printf("sprintf(NULL) did give an error:\n errno=%d.\n", errno); + } + + /* snprintf() must measure the length of the formatted output even when the + ** buffer size is zero. A zero pointer is not an error, in that case. + */ + + size = snprintf(NULL, 0, format, arg1, arg2); + if (size != STRING_SIZE) { + ++failures; + printf("snprintf(NULL,0) gave the wrong size:\n %d.\n", size); + } + + if (failures != 0) { + printf("There were %u", failures); + } else { + printf("There were no"); + } + printf(" failures.\nTap a key. "); + cgetc(); + + return failures; +}