]> git.sur5r.net Git - cc65/commitdiff
Merge pull request #1 from cc65/master
authorsilverdr <silverdr@wfmh.org.pl>
Fri, 26 Feb 2016 22:42:50 +0000 (23:42 +0100)
committersilverdr <silverdr@wfmh.org.pl>
Fri, 26 Feb 2016 22:42:50 +0000 (23:42 +0100)
sync

314 files changed:
.travis.yml
LICENSE
Makefile.travis
README.md
asminc/c64.inc
asminc/pce.inc [new file with mode: 0644]
asminc/pet.inc
asminc/plus4.inc
asminc/vic20.inc
cfg/apple2-overlay.cfg
cfg/apple2-system.cfg
cfg/apple2.cfg
cfg/apple2enh-overlay.cfg
cfg/apple2enh-system.cfg
cfg/apple2enh.cfg
cfg/atari-cart.cfg
cfg/atari-cassette.cfg
cfg/atari-overlay.cfg
cfg/atari.cfg
cfg/atarixl-largehimem.cfg
cfg/atarixl-overlay.cfg
cfg/atarixl.cfg
cfg/atmos.cfg
cfg/c128-overlay.cfg
cfg/c128.cfg
cfg/c16.cfg
cfg/c64-overlay.cfg
cfg/c64.cfg
cfg/cbm510.cfg
cfg/cbm610.cfg
cfg/osic1p-asm.cfg [new file with mode: 0644]
cfg/osic1p.cfg [new file with mode: 0644]
cfg/pce.cfg [new file with mode: 0644]
cfg/pet.cfg
cfg/plus4.cfg
cfg/vic20-32k.cfg
cfg/vic20.cfg
doc/Makefile
doc/atmos.sgml
doc/c64.sgml
doc/ca65.sgml
doc/cc65.sgml
doc/chrcvt.sgml [new file with mode: 0644]
doc/customizing.sgml
doc/da65.sgml
doc/funcref.sgml
doc/index.sgml
doc/intro.sgml
doc/nes.sgml
doc/osi.sgml [new file with mode: 0644]
doc/pce.sgml [new file with mode: 0644]
doc/sim65.sgml [new file with mode: 0644]
doc/smc.sgml
include/ace.h
include/assert.h
include/cbm.h
include/conio.h
include/dbg.h
include/lynx.h
include/mouse.h
include/nes.h
include/osic1p.h [new file with mode: 0644]
include/pce.h [new file with mode: 0644]
include/stdlib.h
include/time.h
include/zlib.h
libsrc/Makefile
libsrc/apple2/crt0.s
libsrc/apple2/exec.s
libsrc/apple2/initcwd.s
libsrc/apple2/irq.s
libsrc/apple2/mainargs.s
libsrc/apple2/targetutil/loader.s
libsrc/atari/dosdetect.s
libsrc/atari/getargs.s
libsrc/atari/getdefdev.s
libsrc/atari/initcwd.s
libsrc/atari/mcbpm.s
libsrc/atari5200/conioscreen.s
libsrc/atmos/bashdr.s [new file with mode: 0644]
libsrc/atmos/crt0.s
libsrc/atmos/tapehdr.s [new file with mode: 0644]
libsrc/c128/crt0.s
libsrc/c128/emd/c128-ram.s
libsrc/c128/mainargs.s
libsrc/c128/mcbdefault.s
libsrc/c128/randomize.s
libsrc/c128/systime.s
libsrc/c16/crt0.s
libsrc/c16/mainargs.s
libsrc/c16/randomize.s
libsrc/c64/bordercolor.s [new file with mode: 0644]
libsrc/c64/color.s
libsrc/c64/crt0.s
libsrc/c64/extra/soft80.s [new file with mode: 0644]
libsrc/c64/extra/soft80mono.s [new file with mode: 0644]
libsrc/c64/mainargs.s
libsrc/c64/mcbdefault.s
libsrc/c64/mcbspritedata.s [new file with mode: 0644]
libsrc/c64/randomize.s
libsrc/c64/soft80.inc [new file with mode: 0644]
libsrc/c64/soft80_cgetc.s [new file with mode: 0644]
libsrc/c64/soft80_charset.s [new file with mode: 0644]
libsrc/c64/soft80_color.s [new file with mode: 0644]
libsrc/c64/soft80_conio.s [new file with mode: 0644]
libsrc/c64/soft80_cputc.s [new file with mode: 0644]
libsrc/c64/soft80_kclrscr.s [new file with mode: 0644]
libsrc/c64/soft80_kplot.s [new file with mode: 0644]
libsrc/c64/soft80_scrsize.s [new file with mode: 0644]
libsrc/c64/soft80mono_cgetc.s [new file with mode: 0644]
libsrc/c64/soft80mono_color.s [new file with mode: 0644]
libsrc/c64/soft80mono_conio.s [new file with mode: 0644]
libsrc/c64/soft80mono_cputc.s [new file with mode: 0644]
libsrc/c64/soft80mono_kclrscr.s [new file with mode: 0644]
libsrc/c64/soft80mono_kplot.s [new file with mode: 0644]
libsrc/c64/systime.s
libsrc/cbm/cbm_load.c
libsrc/cbm/chline.s
libsrc/cbm/clinechars.s [new file with mode: 0644]
libsrc/cbm/cvline.s
libsrc/cbm/exec.c
libsrc/cbm/execvars.s
libsrc/cbm/filedes.s
libsrc/cbm/filevars.s
libsrc/cbm/mcbpointercolor.s [new file with mode: 0644]
libsrc/cbm/mcbpointershape.s [new file with mode: 0644]
libsrc/cbm/read.s
libsrc/cbm/write.s
libsrc/cbm510/mainargs.s
libsrc/cbm510/mcbdefault.s
libsrc/cbm510/randomize.s
libsrc/cbm610/mainargs.s
libsrc/cbm610/randomize.s
libsrc/common/_afailed.c
libsrc/common/_cwd.s
libsrc/common/_directerrno.s [new file with mode: 0644]
libsrc/common/_mappederrno.s [new file with mode: 0644]
libsrc/common/_printf.h
libsrc/common/bsearch.c
libsrc/common/errno.s
libsrc/common/interrupt.s
libsrc/common/longjmp.s
libsrc/common/memmove.s
libsrc/common/moveinit.s [new file with mode: 0644]
libsrc/common/qsort.c
libsrc/common/setjmp.s
libsrc/common/vfprintf.s
libsrc/common/vsnprintf.s
libsrc/common/zerobss.s
libsrc/conio/vcprintf.s
libsrc/conio/vcscanf.s
libsrc/dbg/dbgdump.s
libsrc/joystick/joy-kernel.s
libsrc/nes/irq.s [new file with mode: 0644]
libsrc/nes/joy/nes-stdjoy.s
libsrc/osic1p/bootstrap.s [new file with mode: 0644]
libsrc/osic1p/cclear.s [new file with mode: 0644]
libsrc/osic1p/cgetc.s [new file with mode: 0644]
libsrc/osic1p/chline.s [new file with mode: 0644]
libsrc/osic1p/crt0.s [new file with mode: 0644]
libsrc/osic1p/ctype.s [new file with mode: 0644]
libsrc/osic1p/cvline.s [new file with mode: 0644]
libsrc/osic1p/extra/screen-s3-32x28.s [new file with mode: 0644]
libsrc/osic1p/extzp.inc [new file with mode: 0644]
libsrc/osic1p/extzp.s [new file with mode: 0644]
libsrc/osic1p/gotox.s [new file with mode: 0644]
libsrc/osic1p/gotoxy.s [new file with mode: 0644]
libsrc/osic1p/gotoy.s [new file with mode: 0644]
libsrc/osic1p/kbhit.s [new file with mode: 0644]
libsrc/osic1p/oserror.s [new file with mode: 0644]
libsrc/osic1p/osic1p.inc [new file with mode: 0644]
libsrc/osic1p/osiscreen.inc [new file with mode: 0644]
libsrc/osic1p/screen-c1p-24x24.s [new file with mode: 0644]
libsrc/osic1p/wherex.s [new file with mode: 0644]
libsrc/osic1p/wherey.s [new file with mode: 0644]
libsrc/pce/_scrsize.s [new file with mode: 0644]
libsrc/pce/chline.s [new file with mode: 0644]
libsrc/pce/clock.s [new file with mode: 0644]
libsrc/pce/clrscr.s [new file with mode: 0644]
libsrc/pce/color.s [new file with mode: 0644]
libsrc/pce/conio.s [new file with mode: 0644]
libsrc/pce/cputc.s [new file with mode: 0644]
libsrc/pce/crt0.s [new file with mode: 0644]
libsrc/pce/ctype.s [new file with mode: 0644]
libsrc/pce/cvline.s [new file with mode: 0644]
libsrc/pce/extzp.inc [new file with mode: 0644]
libsrc/pce/extzp.s [new file with mode: 0644]
libsrc/pce/gotoxy.s [new file with mode: 0644]
libsrc/pce/irq.s [new file with mode: 0644]
libsrc/pce/joy/pce-stdjoy.s [new file with mode: 0644]
libsrc/pce/joy_stat_stddrv.s [new file with mode: 0644]
libsrc/pce/joy_stddrv.s [new file with mode: 0644]
libsrc/pce/kplot.s [new file with mode: 0644]
libsrc/pce/libref.s [new file with mode: 0644]
libsrc/pce/memcpy.s [new file with mode: 0644]
libsrc/pce/memmove.s [new file with mode: 0644]
libsrc/pce/memset.s [new file with mode: 0644]
libsrc/pce/psg.s [new file with mode: 0644]
libsrc/pce/revers.s [new file with mode: 0644]
libsrc/pce/ticktock.s [new file with mode: 0644]
libsrc/pce/vce.s [new file with mode: 0644]
libsrc/pce/vdc.s [new file with mode: 0644]
libsrc/pce/vga.inc [new file with mode: 0644]
libsrc/pce/waitvblank.s [new file with mode: 0644]
libsrc/pet/crt0.s
libsrc/pet/mainargs.s
libsrc/pet/randomize.s
libsrc/plus4/crt0.s
libsrc/plus4/mainargs.s
libsrc/plus4/randomize.s
libsrc/runtime/callmain.s
libsrc/runtime/stkchk.s
libsrc/sim6502/errno.s [deleted file]
libsrc/vic20/crt0.s
libsrc/vic20/mainargs.s
libsrc/vic20/randomize.s
libsrc/zlib/uncompress.c
samples/Makefile
samples/README
samples/hello.c
samples/mousetest.c
samples/sieve.c
src/ar65/exports.c
src/ca65/expr.c
src/ca65/feature.c
src/ca65/feature.h
src/ca65/filetab.c
src/ca65/global.c
src/ca65/global.h
src/ca65/instr.c
src/ca65/macro.c
src/ca65/main.c
src/ca65/pseudo.c
src/ca65/scanner.c
src/ca65/symentry.c
src/ca65/symtab.c
src/ca65/token.h
src/cc65/codeinfo.c
src/cc65/coptshift.c
src/cc65/coptshift.h
src/cc65/coptstop.c
src/cc65/datatype.c
src/cc65/datatype.h
src/cc65/declare.c
src/cc65/expr.c
src/cc65/function.c
src/cc65/global.c
src/cc65/global.h
src/cc65/main.c
src/cc65/preproc.c
src/cc65/symentry.c
src/cc65/symtab.c
src/cc65/typecmp.c
src/cl65/main.c
src/cl65/spawn-amiga.inc
src/cl65/spawn-unix.inc
src/common/cmdline.c
src/common/cmdline.h
src/common/target.c
src/common/target.h
src/common/version.c
src/da65/attrtab.c
src/da65/attrtab.h
src/da65/data.c
src/da65/infofile.c
src/da65/main.c
src/da65/output.c
src/da65/output.h
src/da65/segment.c
src/da65/segment.h
src/dbginfo/dbgsh.c
src/ld65/config.c
src/ld65/main.c
src/sim65/main.c
src/sim65/paravirt.c
test/Makefile
test/err/Makefile
test/err/cc65091001.c
test/err/cc65150311-1.c [new file with mode: 0644]
test/err/cc65150311-10.c [new file with mode: 0644]
test/err/cc65150311-11.c [new file with mode: 0644]
test/err/cc65150311-2.c [new file with mode: 0644]
test/err/cc65150311-3.c [new file with mode: 0644]
test/err/cc65150311-4.c [new file with mode: 0644]
test/err/cc65150311-5.c [new file with mode: 0644]
test/err/cc65150311-6.c [new file with mode: 0644]
test/err/cc65150311-7.c [new file with mode: 0644]
test/err/cc65150311-8.c [new file with mode: 0644]
test/err/cc65150311-9.c [new file with mode: 0644]
test/err/static-2.c [new file with mode: 0644]
test/err/static-3.c [new file with mode: 0644]
test/err/static-4.c [new file with mode: 0644]
test/misc/Makefile
test/misc/cc65141011.c [new file with mode: 0755]
test/ref/Makefile
test/ref/otccex.c
test/val/Makefile
test/val/add3a.c [new file with mode: 0755]
test/val/add5.c [new file with mode: 0644]
test/val/casttochar.c [new file with mode: 0755]
test/val/cc65141002.c [new file with mode: 0755]
test/val/cc65141022.c [new file with mode: 0755]
test/val/cc65150311.c [new file with mode: 0644]
test/val/pointed-array.c [new file with mode: 0644]
test/val/ptrfunc.c
test/val/rotate8.c [new file with mode: 0644]
test/val/static-1.c [new file with mode: 0644]
testcode/assembler/paramcount.s [new file with mode: 0644]
testcode/lib/.gitignore [new file with mode: 0644]
testcode/lib/conio.c [new file with mode: 0644]
testcode/lib/em-test.c
testcode/lib/pce/Makefile [new file with mode: 0644]
testcode/lib/pce/conio.c [new file with mode: 0644]
testcode/lib/snprintf-test.c [new file with mode: 0644]

index a11412230b0f3e7fbf199f3495a26662a7d42154..10ea789cf3fbf9616a33db124139758c4643348c 100644 (file)
@@ -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 03eefac6776a8137107e30f4b634e9ec586e901b..88cacf1486f5b3eca553241204427913008887ab 100644 (file)
--- 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.
index 78ded63e601479cfca5b73a4cbe750b1f1dd3049..4c0f688f82969396473d7a5d3facdc391a54454a 100644 (file)
@@ -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
 
index bf7d6dcdee78b2b99f2e5d959bb6f6b51ca3510a..a0455cbe6b99998b8e6728a6caefc73b6c1c590e 100644 (file)
--- 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.
index f450fcc0b4386be060980e26f906e8a9f4172f81..ababb1ea0cdc2f933535237aa79aa39747811e57 100644 (file)
@@ -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 (file)
index 0000000..623ab4d
--- /dev/null
@@ -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
index 1ebf391f9f5a41b8c3ce4f410660067a676600e0..a745a89c8b1693a4b1a065c4790f710627c457d1 100644 (file)
@@ -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
index 17e250508b71e63fe43bca93c39ff2d90663abf1..69b2298a37977467d55584eafd418a15cb7455df 100644 (file)
@@ -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
index c42db4258c4048f015b767a8e4ec4ac664aa527b..12424dc116626bc2267db0a812463430b068a927 100644 (file)
@@ -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
index d0b34692f4d17905e088c804a41393d9844c532c..244e4582f827a70be5806fc2a1e041c5a706da1a 100644 (file)
@@ -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;
index 33ab04f5e30920b0ae3c723c093aca66dd269e73..f07208e4545b79c00cac17ef541332ed5f56c548 100644 (file)
@@ -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;
index 5673302d10292d2567ed8b259c9ffed610790aab..27eb706c486e143d2ffca0c25c5d2185b91bc5c8 100644 (file)
@@ -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;
index d0b34692f4d17905e088c804a41393d9844c532c..244e4582f827a70be5806fc2a1e041c5a706da1a 100644 (file)
@@ -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;
index 33ab04f5e30920b0ae3c723c093aca66dd269e73..f07208e4545b79c00cac17ef541332ed5f56c548 100644 (file)
@@ -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;
index 5673302d10292d2567ed8b259c9ffed610790aab..27eb706c486e143d2ffca0c25c5d2185b91bc5c8 100644 (file)
@@ -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;
index db9486a9fc7d0d6a3d215bcef712766fe310b05e..58457c60678b07a64deb0413bd11481926bb287d 100644 (file)
@@ -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;
index 2116aecd0d496a9ad1a70ed6579e8ebda6ec8ac8..80b5c695f12976a6a8f26e6d1bc5331295a6cb8c 100644 (file)
@@ -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;
index 1d339b2081dc7f1b32652d898abf0c75b752de1c..b3abad988e4a1905d37866c2f4c4fe96f7d8c3b2 100644 (file)
@@ -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;
index dce593f0532d09ae5a59a78a037107ea1b52130e..97b289d7e7a27ce5200732e394c48f9e4e752d42 100644 (file)
@@ -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;
index 01fc76a2680c39dbef65433e70c13cbbfe444e04..f96096995aaefdea196077744b14bd54aa5f6280 100644 (file)
@@ -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;
index 68d0f524e07622f3bec178aea49228af7ecd9dee..7356fc03e0487bad3fde2224c54e92ec850d6293 100644 (file)
@@ -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;
index aad3ce613e692e07a45bc3965845c291df6b97f1..84992a205fd98995c69cc64cfd0754d0298af575 100644 (file)
@@ -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;
index 137c0e9a9d617aeb83bb74f2d08d5371484ce754..a1f935efa60b37367d292916aff78cfebe7d1149 100644 (file)
@@ -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,
index e16ad4b2e5231355f61653ec31af551d2473e74b..f2cc3c40cd57a6ef2f3dfd9a830a0e91bb6de8bb 100644 (file)
@@ -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;
index 0e1259111b180bbead8ae99ea9185861d019a49d..ef2aa418484d4930499fa93595e012e4b4775bc6 100644 (file)
@@ -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;
 }
index 78c1739d3561fb8d241e2cf42f33d774a2ae2ae7..efb42991f60b132b058a2b416007ae3f21dc0077 100644 (file)
@@ -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;
 }
index 2f7693e6ea79c6b5c3bfce8d4e5c90c9e6733f0f..1c3b19c09489f1a90b742ba82f36bdea3d186348 100644 (file)
@@ -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,
index 5d8befd020e5052432b0f14a357e74a528b76d5e..2a105c7f1cd9a35a1b5dd74b9469b22029865725 100644 (file)
@@ -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,
index 7635c6eeb523c63d5462b2a697331c27c3c3bd93..d0775b6f2e4f56c162a3f47e064ab5de611ee5b8 100644 (file)
@@ -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;
index 48b5eba0cc73e459ba86a6d29d7645fd9d6ce4a6..ae66f4c4acf7079840f4c55e45c75df8dacf0923 100644 (file)
@@ -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 (file)
index 0000000..4000890
--- /dev/null
@@ -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 (file)
index 0000000..fd9aa60
--- /dev/null
@@ -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 (file)
index 0000000..9128eb7
--- /dev/null
@@ -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__;
+}
index ef8b82e5454ad298847ba09b23f915b488402da5..80d89ee50a45cd069554d96eba96ab502998059a 100644 (file)
@@ -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;
 }
index c756f45a1e9f0a3c0695af33cefe4e2c30b110a6..6eeddf12ed769a370da7d2a956c6fdfc37ea4de5 100644 (file)
@@ -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;
 }
index c66b35247c9da55a2048ad16edf395609424f539..23cd718dfcee89ceb4e8ea1d55701a2e5aa6472c 100644 (file)
@@ -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;
 }
index f356eb61e0a96a93e2fdce3ba5b41595f0575adb..9a5ce9a63f8e59ca1d33fca3a2af369d085042fa 100644 (file)
@@ -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;
 }
index 02ed6b1d3c6119770e55d1d9d7aa2d2237658d0c..967443ef0091eb12be9bcf7e6c6595c1f9a227c3 100644 (file)
@@ -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:
 
index 805fc7a03a436991d1ea163180fe25c8175b1d03..68f7f9d6508937c62d42aca465f5a9318ef155de 100644 (file)
@@ -7,7 +7,7 @@
 <url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
 <url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">,<newline>
 <url url="mailto:greg.king5@verizon.net" name="Greg King">
-<date>2014-03-27
+<date>2015-01-09
 
 <abstract>
 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.
 
 
+
 <sect>Binary format<p>
 
 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 &dollar;500.
+is a machine language program with a one-line BASIC stub that jumps to the
+machine-language part through <tt/CALL/.  It has one sacrificial byte attached
+to the end (a bug in the Oric ROM means that BASIC can put a variable on top
+of the last byte that was loaded).  It has a 24-byte tape header.  A file can
+be CLOADed as a BASIC program, and started by typing <tt/RUN/.  The standard
+load address is &dollar;501.
+
 
 
 <sect>Memory layout<p>
 
-In the standard setup, cc65 generated programs use the memory from
-&dollar;500 to &dollar;9800, so nearly 37K of memory (including the stack) is
+In the standard setup, cc65-generated programs use the memory from
+&dollar;0501 to &dollar;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, <tt/-D __GRAB__=1/, when building the
+program, to include the graphics screen RAM.  Then, nearly 44K of memory
+(&dollar;0501 to &dollar;B400) is available.
+
 Special locations:
 
 <descrip>
   <tag/Stack/
-  The C runtime stack is located at &dollar;97FF and growing downwards.
+  The C runtime stack is located at &dollar;97FF (or &dollar;B3FF), and grows
+  downwards.
 
   <tag/Heap/
-  The C heap is located at the end of the program and grows towards the C
+  The C heap is located at the end of the program, and grows towards the C
   runtime stack.
 
 </descrip><p>
@@ -90,7 +102,7 @@ structures; accessing the struct fields will access the chip registers.
 <descrip>
 
   <tag><tt/VIA/</tag>
-  Access to the VIA (versatile interface adapter) chip is available via the
+  Access to the VIA (Versatile Interface Adapter) chip is available via the
   <tt/VIA/ variable. The structure behind this variable is explained in <tt/_6522.h/.
 
 </descrip><p>
@@ -117,7 +129,8 @@ The names in the parentheses denote the symbols to be used for static linking of
 
 <sect1>Graphics drivers<p>
 
-The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/, point to <tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/.
+The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/,
+point to <tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/.
 
 <descrip>
 
@@ -175,13 +188,14 @@ No mouse drivers are currently available for the Atmos.
 
 <sect1>Disk I/O<p>
 
-The existing library for the Atmos doesn't implement C file
-I/O. There are hacks for the <tt/read()/ and <tt/write()/ routines in
-place, which will make functions work that read from and write to <tt/stdout/
-(like <tt/printf()/). However, those functions have some shortcomings which
-won't be fixed, because they're going to be replaced anyway.
+The existing library for the Atmos doesn't implement C file I/O. There are
+hacks for the <tt/read()/ and <tt/write()/ routines in place, which will make
+functions work that read from <tt/stdin/ and write to <tt/stdout/ and
+<tt/stderr/ (such as <tt/printf()/). However, those functions have some
+shortcomings which won't be fixed, because they're going to be replaced
+anyway.
 
-To be more concrete, the limitation means that you cannot use any of the
+To be more concrete, that limitation means that you cannot use any of the
 following functions (and a few others):
 
 <itemize>
@@ -202,7 +216,14 @@ following functions (and a few others):
 
 <sect1>Function keys<p>
 
-These are defined to be FUNCT + number key.
+They are defined to be FUNCT + a number key.
+
+
+<sect1>Capitals lock<p>
+
+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.
 
 
 <sect1>Passing arguments to the program<p>
@@ -211,10 +232,12 @@ Command-line arguments can be passed to <tt/main()/. Since that is not
 supported directly by BASIC, the following syntax was chosen:
 
 <tscreen><verb>
-    CALL#500:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
+    RUN:REM arg1 " ARG2 IS QUOTED" ARG3 "" ARG5
 </verb></tscreen>
 
 <enum>
+<item>You must turn <tt/CAPS/ lock off (tap CTRL-T) when you want to type
+      lower-case arguments (but, <tt/RUN/ and <tt/REM/ must be UPPER-case).
 <item>Arguments are separated by spaces.
 <item>Arguments may be quoted.
 <item>Leading and trailing spaces around an argument are ignored. Spaces within
@@ -225,6 +248,15 @@ supported directly by BASIC, the following syntax was chosen:
 </enum>
 
 
+<sect1>Automatic starting<p>
+
+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 <tt/RUN/ command).
+But, if you want to create a program that will start running immediately after
+it is loaded, then you can use the linker command-line option
+<tt/-D __AUTORUN__=$C7/.
+
+
 <sect1>Interrupts<p>
 
 The runtime for the Atmos uses routines marked as <tt/.INTERRUPTOR/ for
index ca99e0061631083865afb1663ca92021923bc03e..8767d212d181c2e06cf3b46613015d44abcf47bf 100644 (file)
@@ -116,6 +116,39 @@ cl65 -o file.prg -u __EXEHDR__ -t c64 -C c64-asm.cfg source.s
 Please note that in this case a changed start address doesn't make sense,
 since the program must be loaded to the BASIC start address.
 
+<sect>Extras<p>
+
+<sect1>80 Columns conio driver<p>
+
+The C64 package comes with an alternative software driven 80 columns
+module <tt/c64-soft80.o/ which uses the memory under I/O between &dollar;d000
+and &dollar;ffff.
+
+In memory constrained situations the memory from &dollar;400 to &dollar;7FF
+can be made available to a program by calling <tt/_heapadd ((void *) 0x0400, 0x0400);/
+at the beginning of <tt/main()/. Doing so is beneficial even if the program
+doesn't use the the heap explicitly because loading a driver uses the heap implicitly.
+
+Using <tt/c64-soft80.o/ is as simple as placing it on the linker command
+line like this:
+
+<tscreen><verb>
+cl65 -t c64 myprog.c c64-soft80.o
+</verb></tscreen>
+
+Note that the soft80 conio driver is incompatible with the
+<tt/c64-ram.emd (c64_ram_emd)/ extended memory driver and the
+ <tt/c64-hi.tgi (c64_hi_tgi)/ graphics driver.
+
+<sect2>80 Columns conio driver (monochrome)<p>
+
+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.
+
+<tscreen><verb>
+cl65 -t c64 myprog.c c64-soft80mono.o
+</verb></tscreen>
 
 <sect>Platform-specific header files<p>
 
@@ -216,6 +249,9 @@ configuration.
   palette of the 16 C64 colors).
 </descrip><p>
 
+Note that the graphics drivers are incompatible with the
+<tt/c64-ram.emd (c64_ram_emd)/ extended memory driver and the
+ <tt/c64-soft80.o/ software 80 columns conio driver.
 
 <sect1>Extended memory drivers<p>
 
@@ -241,7 +277,7 @@ configuration.
   <tag><tt/c64-ram.emd (c64_ram_emd)/</tag>
   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!
 
   <tag><tt/c64-ramcart.emd (c64_ramcart_emd)/</tag>
   A driver for the RamCart 64/128 written and contributed by Maciej Witkowiak.
index 32cf0b80b6eec3a9570ac0de0fa4b01fbc1bd916..213033cd4b3ef100ad8bbf6ac3eeb4dea3fecb47 100644 (file)
@@ -2,11 +2,12 @@
 
 <article>
 <title>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/(&dollar;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, '(&dollar;00,x)' is passed to the macro, this time
+In the second case, '<tt/(&dollar;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>
-
-
-
index a6b4a07eebbb701c4b206f6d713faff1e8dbdd09..9198d6982d1bc6b5ff91d1009195079c2fee4c84 100644 (file)
@@ -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>
        &lt;return type&gt; fastcall &lt;function name&gt; (&lt;parameter list&gt;)
        </verb></tscreen>
        or
        <tscreen><verb>
-               &lt;return type&gt; __fastcall__ &lt;function name&gt; (&lt;parameter list&gt;)
+       &lt;return type&gt; __fastcall__ &lt;function name&gt; (&lt;parameter list&gt;)
        </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 &lsqb;<tt/.../&rsqb;) always use that
+        convention. The syntax for a function declaration using cdecl is
+
+        <tscreen><verb>
+        &lt;return type&gt; cdecl &lt;function name&gt; (&lt;parameter list&gt;)
+        </verb></tscreen>
+        or
+        <tscreen><verb>
+        &lt;return type&gt; __cdecl__ &lt;function name&gt; (&lt;parameter list&gt;)
+        </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 (file)
index 0000000..848fb52
--- /dev/null
@@ -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>
index 23cf8c5e8f68397a24a9dda5fb895ee2b543257d..0a0b8c87ec293f8aa0a55b3c9f5cf4039e760400 100644 (file)
@@ -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.
index 2b8cdb2a39914362c8b8ce7a9685769564f3fcf4..df8cd777293817fff8d59abe317c748df80cd6ee 100644 (file)
@@ -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>
-
-
-
-
index 60b8360edabbe861cbb99af6174caa59d68302e3..a2ccf6c73c653df3a0ddf395bbafd93085bea59c 100644 (file)
@@ -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(&amp;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">.
index 7de8b26cea1270d3dc1b75541ef930a211c1cf28..b6ef06ef9b2972b98ea193b88fbfdfeb653729da 100644 (file)
@@ -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 &amp; 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&uuml;gers macro package for writing self modifying
+  Describes Christian Kr&uuml;ger's macro package for writing self modifying
   assembler code.
 
   <tag><url name="6502 Binary Relocation Format document"
   <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.
 
   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.
 
 
 </article>
-
index 02c5c83d5f58ff9d71d515e0634a8f3396927388..d92fd1d20f2216d48338a9137a0a93c2a4e4b07d 100644 (file)
@@ -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&uuml;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 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
index ca9ce72b351eb93e288d372c34619887e2859291..98c25b6af934faebfab7f4bf3446f8f5fde2433b 100644 (file)
@@ -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 (file)
index 0000000..ab1b4ce
--- /dev/null
@@ -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&uuml;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 &dollar;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 &dollar;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 &dollar;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 &dollar;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 &dollar;D085 and corresponds to conio cursor
+  position (0, 0).
+
+</descrip><p>
+
+Example for building a program with start address &dollar;0300, stack size
+&dollar;0200 and RAM size &dollar;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 &lt;configfile&gt;/.
+
+<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 (file)
index 0000000..ba59c31
--- /dev/null
@@ -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 &dollar;8000 - &dollar;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 &dollar;0000,
+  the Font is located at VRAM &dollar;2000.
+
+  <tag/Stack/
+  The C runtime stack is located in system RAM at &dollar;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 &dollar;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 &dollar;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&amp;category=&amp;platform=4&amp:game=&amp;author=&amp;perpage=20&amp;level=&amp;title=&amp;desc=&amp;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 (file)
index 0000000..24b4383
--- /dev/null
@@ -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>
index 240c78e7baa8aaa112aeabdc0c1add11aea80010..4f3e2ace408c71cf7e84558625b0a36ed0f04d70 100644 (file)
@@ -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>
 
index 8d91300852742dc17d3da43aefb433fcaf270eba..fba672227715d5902b63161a82ef28cfc579f97f 100644 (file)
@@ -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);
 
 
 
index 87bc4ff02dcc459a6ef6c1ce38a9828f68aae1ed..504964dc2d04e07441e3e23d3c33803c11959b11 100644 (file)
@@ -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
 
index 730b0b49e6f06d5502bb2003b776a92309bdb7ab..701924d5714f9485d3dda640de3602a8442755d8 100644 (file)
@@ -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).
index 54667a3ca90e8e8164b2e1d3a355d489c8ca8940..8638e94d425b26ceaf4fab599eacc1204ee4e805 100644 (file)
 #  include <lynx.h>
 #elif defined(__NES__)
 #  include <nes.h>
+#elif defined(__OSIC1P__)
+#  include <osic1p.h>
+#elif defined(__PCE__)
+#  include <pce.h>
 #endif
 
 
index 734ca06b8950eb31af02851deec1342a303b92f2..7b4f67e3143c4407b020a40120b0a2e7253a88ab 100644 (file)
@@ -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
index e9c7029940237ee15b062e0f7457c60d1c27fad1..72f3d5bfd6a4221fc2b98e69986544e3d8a9e73c 100644 (file)
@@ -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 */
 
 /*****************************************************************************/
index ac75956c06263765538c8539eb483e720d49c7a8..8bd9a00ff012787f19df9f9cae0772bd65c99910 100644 (file)
@@ -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
-
-
-
index 3ad4422809a9eb05072b41329d4587fb04323733..a472a0f3c9cd587369163ae43a27cf54ca40ce1e 100644 (file)
 /* 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 (file)
index 0000000..57fe0cd
--- /dev/null
@@ -0,0 +1,47 @@
+/*****************************************************************************/\r
+/*                                                                           */\r
+/*                                osic1p.h                                   */\r
+/*                                                                           */\r
+/*                Challenger 1P system specific definitions                  */\r
+/*                                                                           */\r
+/*                                                                           */\r
+/*                                                                           */\r
+/* (C) 2015 Stephan Muehlstrasser                                            */\r
+/*                                                                           */\r
+/*                                                                           */\r
+/* This software is provided 'as-is', without any expressed or implied       */\r
+/* warranty.  In no event will the authors be held liable for any damages    */\r
+/* arising from the use of this software.                                    */\r
+/*                                                                           */\r
+/* Permission is granted to anyone to use this software for any purpose,     */\r
+/* including commercial applications, and to alter it and redistribute it    */\r
+/* freely, subject to the following restrictions:                            */\r
+/*                                                                           */\r
+/* 1. The origin of this software must not be misrepresented; you must not   */\r
+/*    claim that you wrote the original software. If you use this software   */\r
+/*    in a product, an acknowledgment in the product documentation would be  */\r
+/*    appreciated but is not required.                                       */\r
+/* 2. Altered source versions must be plainly marked as such, and must not   */\r
+/*    be misrepresented as being the original software.                      */\r
+/* 3. This notice may not be removed or altered from any source              */\r
+/*    distribution.                                                          */\r
+/*                                                                           */\r
+/*****************************************************************************/\r
+\r
+#ifndef _OSIC1P_H\r
+#define _OSIC1P_H\r
+\r
+/* Check for errors */\r
+#if !defined(__OSIC1P__)\r
+#  error "This module may only be used when compiling for the Challenger 1P!"\r
+#endif\r
+\r
+/* The following #defines will cause the matching functions calls in conio.h\r
+** to be overlaid by macros with the same names, saving the function call\r
+** overhead.\r
+*/\r
+#define _textcolor(color)       COLOR_WHITE\r
+#define _bgcolor(color)         COLOR_BLACK\r
+#define _bordercolor(color)     COLOR_BLACK\r
+\r
+#endif\r
diff --git a/include/pce.h b/include/pce.h
new file mode 100644 (file)
index 0000000..7700654
--- /dev/null
@@ -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
index eac5629a82542c18461d1f291deb6a7f9b309e46..3103172d8f25cc657310bc20afc3cc0aee7ac9ee 100644 (file)
@@ -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);
index c70ffa718b6a2de36ab8016e198d20fcac1a3dcb..12f130f5235b4add8bc9752676f9811d6216d4cb 100644 (file)
@@ -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 */
index 9bc5dcb270a583b18728947222d1788b2c7c7154..8fa6a2bd12c7c035e545e7a04f7e79e0a3fd6bbb 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */\r
 /*                                                                           */\r
 /*                                                                           */\r
-/* (C) 2000-2001 Piotr Fusik <fox@scene.pl>                                  */\r
+/* (C) 2000-2015 Piotr Fusik <fox@scene.pl>                                  */\r
 /*                                                                           */\r
 /* This file is based on the zlib.h from 'zlib' general purpose compression  */\r
 /* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler.    */\r
@@ -83,8 +83,8 @@ unsigned __fastcall__ inflatemem (char* dest, const char* source);
 */\r
 \r
 \r
-int uncompress (char* dest, unsigned* destLen,\r
-                const char* source, unsigned sourceLen);\r
+int __fastcall__ uncompress (char* dest, unsigned* destLen,\r
+                             const char* source, unsigned sourceLen);\r
 /*\r
    Original zlib description:\r
 \r
index 6a801695a444f982bb478f03eefe151e3baeb948..d70ad5a3156251e6dfb935a976d7599bae3f8a62 100644 (file)
@@ -24,6 +24,8 @@ TARGETS = apple2    \
           $(GEOS)   \
           lynx      \
           nes       \
+          osic1p    \
+          pce       \
           sim6502   \
           sim65c02  \
           supervision
index 4a7463b273d6f8d7f426c0d3704b3c59d583648b..f061b212be71f58ab4d0712924103ccf37a691e4 100644 (file)
@@ -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"
         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
 
         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
 
index c486306bbde88873de31b77251d05c5a25e39632..d24de604c668bb66d58ce872138ee7ed8f2d52ab 100644 (file)
@@ -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
 
index 044076e3ff4143b63e7f7dabd76037695e016343..7af29c75e78c2ac7902dffdd0045a87bd3734bc7 100644 (file)
@@ -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
index c81fa7108da925541a35d5b7ec8e52ef241406ba..0b05556955aba72c5b89cc539da456a7fa113d04 100644 (file)
@@ -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
index 6b0df4dedb23f483f79f88d79b2e05ba8faa68cd..2e809dc56a7be695f668c52a202d7f82802b1194 100644 (file)
 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
index 0173f6105b75b6c4e08e9b190642e3a77dc4376d..a6cc13cefac090c1b74f650006a9709d43101834 100644 (file)
@@ -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
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
index c60ac479b4b80c5be61a5a81fc7e8eaef101af63..654da55b58b7dd0fc06eb2aadc7097174d243ab5 100644 (file)
@@ -5,7 +5,7 @@
 ;
 
         .include        "atari.inc"
-        .constructor    detect,26
+        .constructor    detect, 26
         .export         __dos_type
 
 ; ------------------------------------------------------------------------
index fdae55364e5628b48cbc21a663114c120a12f3bd..fb3b7bc0304694c108fcac9b64db5bf349a9fdd1 100644 (file)
@@ -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
index 13aa12e046a2def94e80b76ec0a45956fd32c29d..47d8714e65d0a029524dd77a0bc4e750a2199793 100644 (file)
@@ -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!!)
index d7b5743140425cd8a294dd7d4e80e9c4d91aae5c..c292e72c390bad8dfdbcc252b4d37e5a435b633a 100644 (file)
@@ -9,6 +9,8 @@
 
 .proc   initcwd
 
+        lda     #0
+        sta     __cwd
         jsr     findfreeiocb
         bne     oserr
         lda     #GETCWD
         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
index b546faced2ed938fd6a890efdb8f1e609cc1cbca..c5c5dd433467cc3b9bdd53f324c7a36672825802 100644 (file)
@@ -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
index 412dd582d6ddc8c8eafe890107535fbb10a46451..660276675df3694fccec23604e09eb21543419dd 100644 (file)
@@ -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 (file)
index 0000000..e09bc9f
--- /dev/null
@@ -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:
index 1d919f34827712a013bdd16366adeeb39b6de1da..e789b28c279f533b4863ff801689eab1b1a7e5d0 100644 (file)
@@ -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:
+
+; 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"
 
-zpsave: .res    zpspace
+        .res    zpspace - 1
 
 ; ------------------------------------------------------------------------
 
diff --git a/libsrc/atmos/tapehdr.s b/libsrc/atmos/tapehdr.s
new file mode 100644 (file)
index 0000000..d90c908
--- /dev/null
@@ -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)
index 9bfdca49f8957a32782e2c3712151f0702cc7355..4c6a0f7d9530107ef940578d2b6b0ee51f3384db 100644 (file)
@@ -108,7 +108,7 @@ L2:     lda     zpsave,x
 ; ------------------------------------------------------------------------
 ; Data
 
-.segment        "ZPSAVE"
+.segment        "INITBSS"
 
 zpsave: .res    zpspace
 
index bef0a15ee3f2b3f3a358ca1f3c7b3ef0321d717e..3fc52c9cceab238a0a995764bd25bceeacbbaff0 100644 (file)
@@ -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
index fb5fd1554da2d30b8876e6c673d29e5e9d8c7a4b..dcd5a11bd2746af9c0561eae309a1a0dc47daa0d 100644 (file)
@@ -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
-
index 01c54efcab2ec98c2daa467e067cc5100db2da70..1951129a6335f3051fdd2e3d3f6b3cda85c8ef96 100644 (file)
@@ -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"
         .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
index 5c57e04be42abb41321933decf6541dd9ed693be..ae63184a48dcd562cd86ac1513c0949346ef4d55 100644 (file)
@@ -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
 
index 0a7f8f367715f96079582f333ef637685cc276d1..e12d016b810fdcab189c975da586feb88c71f8e5 100644 (file)
@@ -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
-
index 0180ad6713efd5e80097980664ae9f9dc05ec3b6..c4d17952991ce9205120bd1bc0e92ee805607fe4 100644 (file)
@@ -90,7 +90,7 @@ L2:     lda     zpsave,x
 
 ; ------------------------------------------------------------------------
 
-.segment        "ZPSAVE"
+.segment        "INITBSS"
 
 zpsave: .res    zpspace
 
index 0a402d27dc16d79012af026d607af8ffb55eae86..db93ae2e62e46b7ceed43911eab8f5d166c26d4a 100644 (file)
         .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
-
index 903a0809a24becaa6b74123b5d3dfefc8b32ec9c..796ad118be35966aed24e8cf405f3bd073ed0287 100644 (file)
@@ -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 (file)
index 0000000..73dfc0a
--- /dev/null
@@ -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
+
index bfc37193103cb711b4deb24a3b91ecec8539bda7..86d6aefe8758699d83d315f1d780780e600fc995 100644 (file)
@@ -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
-
index 24fe4376bdafde59d78583f5907ad600a80fef74..78268422b0e4f9599597c0c82c80d6939c9e88b5 100644 (file)
@@ -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"
 
 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.
+        tsx
+        stx     spsave          ; Save the system stack ptr
 
-        jsr     zerobss
+; 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.
 
-; Save some system settings; and, set up the stack.
+        ldx     move_init
+        beq     L0
 
-        pla
-        sta     mmusave         ; Save the memory configuration
+; Move the INIT segment from where it was loaded (over the bss segments)
+; into where it must be run (over the BSS segment).
 
-        tsx
-        stx     spsave          ; Save the system stack ptr
+        jsr     moveinit
+        dec     move_init       ; Set to false
 
-        lda     #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
-        sta     sp
-        lda     #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
-        sta     sp+1            ; Set argument stack ptr
+; Save space by putting some of the start-up code in the INIT segment,
+; which can be re-used by the BSS segment, the heap and the C stack.
 
-; Call the module constructors.
+L0:     jsr     runinit
 
-        jsr     initlib
+; Clear the BSS data.
+
+        jsr     zerobss
 
 ; Push the command-line arguments; and, call main().
 
@@ -98,14 +93,47 @@ L2:     lda     zpsave,x
 
         rts
 
+
 ; ------------------------------------------------------------------------
-; Data
 
-.segment        "ZPSAVE"
+.segment        "INIT"
 
-zpsave: .res    zpspace
+runinit:
 
-.bss
+; 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
+
+.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.
 
-spsave: .res    1
 mmusave:.res    1
+spsave: .res    1
+
+move_init:
+        .byte   1
+
+.segment        "INITBSS"
+
+zpsave: .res    zpspace
diff --git a/libsrc/c64/extra/soft80.s b/libsrc/c64/extra/soft80.s
new file mode 100644 (file)
index 0000000..d445c85
--- /dev/null
@@ -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 (file)
index 0000000..6fd2c68
--- /dev/null
@@ -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
index 1c9031eb0b5df4991b969ab0804e3b735d9e1463..a31c1b54f2e0250c37c8676d95dc5ed19c69a53e 100644 (file)
         .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
-
index ffeed45b349b086137119297556bfbcae2bb1370..cd36d8515faaa578b312b708174171cc4eeb611e 100644 (file)
@@ -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 (file)
index 0000000..2c7aa14
--- /dev/null
@@ -0,0 +1,4 @@
+; VIC sprite data for the mouse pointer
+
+        .export         mcb_spritememory  := $0340
+        .export         mcb_spritepointer := $07F8
index c77d6b411bde8d373e9b3ff219a85584e8d70709..d74bae91eea67437f19f23a2ef3dc577f7da1f54 100644 (file)
@@ -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 (file)
index 0000000..ca5c713
--- /dev/null
@@ -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 (file)
index 0000000..ae0e238
--- /dev/null
@@ -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 (file)
index 0000000..69fd352
--- /dev/null
@@ -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 (file)
index 0000000..8c1d113
--- /dev/null
@@ -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 (file)
index 0000000..874d41a
--- /dev/null
@@ -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 (file)
index 0000000..acbe5b5
--- /dev/null
@@ -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 (file)
index 0000000..7c313af
--- /dev/null
@@ -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 (file)
index 0000000..bd52ee6
--- /dev/null
@@ -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 (file)
index 0000000..9f1701a
--- /dev/null
@@ -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 (file)
index 0000000..d99dc77
--- /dev/null
@@ -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 (file)
index 0000000..aa24957
--- /dev/null
@@ -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 (file)
index 0000000..759b280
--- /dev/null
@@ -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 (file)
index 0000000..c89362c
--- /dev/null
@@ -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 (file)
index 0000000..99243c6
--- /dev/null
@@ -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 (file)
index 0000000..b987924
--- /dev/null
@@ -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
index a00df13977fa828864d68137fffb18240792e672..f8cd1b71463b4e2ad5c783a7accf357a068c5fd1 100644 (file)
@@ -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
-
index 695af504b61d0829e5ba7daa05c5738d9f256d0d..c1c6f568af57b69f1f748652706e52b8bedc9eaa 100644 (file)
@@ -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).
index 26603b2febbbcdcfa77dfcb1a6f36b8e6669e79d..fe7e7255d7ce2c272a5be2f513fa2a563990fa66 100644 (file)
@@ -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 (file)
index 0000000..5489657
--- /dev/null
@@ -0,0 +1,6 @@
+;
+; Chars used by chline () and cvline ()
+;
+
+        .exportzp       chlinechar = 64
+        .exportzp       cvlinechar = 93
index f310e43223ee39ca700295de8568104219a5ff64..2cf231e982d714b38b3c5c3feba9040783151239 100644 (file)
@@ -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
index 36c3afe006bb428fb39aa392a1aa31f8fb3300d6..b9c1bdc961e9ca872b2979d84cf2117d9110c441 100644 (file)
@@ -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.
 **
 /* 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 lineconst 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__);
index 02eabc12e2421be531538f590972bf982f9900ef..68f8a5d64e655a7f5b24f5296b46c4da10314e5c 100644 (file)
         .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
+
+.exportzp _txtptr       :=      TXTPTR
 
-_basbuf         :=      BASIC_BUF
-_basbuf_len     =       BASIC_BUF_LEN
+.export   _basbuf       :=      BASIC_BUF
+.exportzp _basbuf_len   =       BASIC_BUF_LEN
index 384313b94713d3a7f2291c27b874db386c52c5c0..ddce1be4da2fd774306e9a4196dffb1fc87ff39a 100644 (file)
@@ -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
index 316cf276211bfd742c8395e1f3795b002c561401..db2dec7b3de1e72fbf3ae7f80621f04a89555b35 100644 (file)
@@ -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 (file)
index 0000000..c9cb633
--- /dev/null
@@ -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 (file)
index 0000000..7364201
--- /dev/null
@@ -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
index aa692a34aed09f120c263647c85e3dc25e7b20d9..e0fd8d51b5dd8aff89d07fffa83ae979c8b309c3 100644 (file)
 
 .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
-
-
index fdf7cfbc18fa354b72284ebbebad77407361123f..e6da59c0f1e00d31d22288b9442ba2e4962dbd7a 100644 (file)
 
 .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
-
-
-
-
index 7eebccbb3e20bb4f3f2c55b7899885dfe77b6116..0ec7d0c4c0ece1532bf0eb24f49899e6e24e7890 100644 (file)
         .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
index 028fb4ec19a701ccb594e99bf0fda6852ed293ca..0db753e927155d78a93153b880f518e4c3602d4a 100644 (file)
@@ -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"
 ; 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
index d5420165cb4c16291c20e695796281cd6042c23d..75c419ccbbcf1b7b7c2ba7a3d3958fc0c367dd8c 100644 (file)
@@ -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
 
index 9388eac8131cda8f9bea86c7fda2ae8d445890bd..02461ac26fb9fa80aa13176325fc36aac48da310 100644 (file)
         .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
index a936f8a2f3c02ce80a4a0428c6174673a8f44f74..d313baa1bfe1a2765d4fdd297d88abae6d939d55 100644 (file)
@@ -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
 
index 4e56b93f23987e0affa6c7b1c54b023fdada10ea..7c6df4a2c10f1ef7d4649cf045520385ba228111 100644 (file)
@@ -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);
index eeda10f1d0dff2dc732fbf5c2289b0cf9f2881a4..7b4031f52ddee7e341a7368f930520cdc86f7731 100644 (file)
         .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 (file)
index 0000000..7942471
--- /dev/null
@@ -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 (file)
index 0000000..33f654c
--- /dev/null
@@ -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
index ffb2443bd931b8dcaf3f9420439424bc834a96c6..7914fa87075e514663f1d02b61b53f1243dc170b 100644 (file)
@@ -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);
 
 
 
index f6d32a5b51963cda50395bfc22bc6723627d6369..aafd28592a5dff14ab5edcbc96a312b7c55d54c4 100644 (file)
@@ -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;
index 3a1f1b6c8ab15cea01ca992c855198b2408a5c17..f448c3c14cb49bb9823a64ebf2c17b337081772b 100644 (file)
@@ -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
-
index e1d53d6dce60099fa90992469d77653eaacccacb..950d3d78745f6fcc9bfae9ea929196ac097e3f88 100644 (file)
@@ -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
-
index a89f97fa07862b8063442eb4ea6f6c8024a4cc0a..e9bac42e626fea7538ab8f174a4b04aa91af5a09 100644 (file)
@@ -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
-
index 94ad7d102878ca64fa82b5d741ae53df423bad9b..9c33124f19e2b1d1d3b33fe13f94d4fc2faff2fa 100644 (file)
@@ -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 (file)
index 0000000..2b22be0
--- /dev/null
@@ -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
index df02095edb36ba3862f2dac756fb6f8562525ebb..991db3ba18d34ac94c35fc67c809f725b65997eb 100644 (file)
@@ -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) {
index a6448b29f89e47d4e0cecbbefa6920b3cedd1c33..a763ac3ecbdeba6a9e43f250c3ac171d499a866d 100644 (file)
@@ -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
index 9812f661bb9b9649b23bad4093cf206c4d15dbce..1225bcc47418c4b4d69efaadc28ef75366703b7b 100644 (file)
@@ -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
index db82bdaf3b8fbb6a7254a4a19143e308c4381675..228e531d0430b72829c6bfdc9aef1a2b75264e86 100644 (file)
@@ -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.
 
-        lda     ccount+0
-        ldx     ccount+1
-        cpx     bufsize+1
+        ldx     bufsize+1
+        bmi     L4              ; -1 -- No buffer
+        lda     bufsize+0
+        cpx     ccount+1
         bne     L2
-        cmp     bufsize+0
+        cmp     ccount+0
 L2:     bcc     L3
-        lda     bufsize+0
-        ldx     bufsize+1
+        lda     ccount+0
+        ldx     ccount+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
 
index de160aeefeb39844a6bdfd914823c4dcf2bc1070..2c500f77397ef6a148a360bcb35a75bc5ca7107e 100644 (file)
@@ -9,7 +9,7 @@
         .importzp       ptr1
 
 
-.segment "INIT"
+.code
 
 zerobss:
         lda     #<__BSS_RUN__
@@ -41,6 +41,3 @@ L3:     cpy     #<__BSS_SIZE__
 ; Done
 
 L4:     rts
-
-
-
index 5dbbc051dea2f876ae501479371de868b78b45d5..06eab44211968d6fe3b2ea3b910b37e0b24d6242 100644 (file)
@@ -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
-
-                      
-
index 67d5f664fda55aa3a61a20dfdce02ee56696a9e1..6893da4efb8c598c2acc62bc6357b0acd270f2dd 100644 (file)
@@ -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
-
index b2045872fadc19f14f0f32b1ace162bafe8ec31f..8ab646d21386b64b1e5302cf433527fe663a92ac 100644 (file)
@@ -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
index 1ba3056d8f66d3399c881eaa23d946720e0a8811..2b1dcf884158f8d34870bacd7737e14137359096 100644 (file)
@@ -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 (file)
index 0000000..9c026f0
--- /dev/null
@@ -0,0 +1,19 @@
+;
+; IRQ handling (NES version)
+;
+
+        .export         initirq, doneirq
+
+; ------------------------------------------------------------------------
+
+.segment        "INIT"
+
+initirq:
+        rts
+
+; ------------------------------------------------------------------------
+
+.code
+
+doneirq:
+        rts
index b50c2124d3e73f81b344d3c5faebdd5e1f72b128..b5e653c162e01ee39c05c0265a950d063efad395 100644 (file)
@@ -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 (file)
index 0000000..2a501b9
--- /dev/null
@@ -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 (file)
index 0000000..2036c38
--- /dev/null
@@ -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 (file)
index 0000000..5ddca28
--- /dev/null
@@ -0,0 +1,50 @@
+;\r
+; char cgetc (void);\r
+;\r
+\r
+        .constructor    initcgetc\r
+        .export         _cgetc\r
+        .import         cursor\r
+\r
+        .include        "osic1p.inc"\r
+        .include        "extzp.inc"\r
+        .include        "zeropage.inc"\r
+\r
+; Initialize one-character buffer that is filled by kbhit()\r
+        .segment        "INIT"\r
+initcgetc:\r
+        lda     #$00\r
+        sta     CHARBUF         ; No character in buffer initially\r
+        rts\r
+\r
+; Input routine from 65V PROM MONITOR, show cursor if enabled\r
+        .code\r
+_cgetc:\r
+        lda     CHARBUF         ; character in buffer available?\r
+        beq     nobuffer\r
+        tax                     ; save character in X\r
+        lda     #$00\r
+        sta     CHARBUF         ; empty buffer\r
+        beq     restorex        ; restore X and return\r
+nobuffer:\r
+        lda     cursor          ; show cursor?\r
+        beq     nocursor\r
+        ldy     CURS_X\r
+        lda     (SCREEN_PTR),y  ; fetch current character\r
+        sta     tmp1            ; save it\r
+        lda     #$A1            ; full white square\r
+        sta     (SCREEN_PTR),y  ; store at cursor position\r
+nocursor:\r
+        jsr     INPUTC          ; get input character in A\r
+        ldx     cursor\r
+        beq     done            ; was cursor on?\r
+        tax                     ; save A in X\r
+        lda     tmp1            ; fetch saved character\r
+        ldy     CURS_X\r
+        sta     (SCREEN_PTR),y  ; store at cursor position\r
+\r
+restorex:\r
+        txa                     ; restore saved character from X\r
+done:\r
+        ldx     #$00            ; high byte of int return value\r
+        rts\r
diff --git a/libsrc/osic1p/chline.s b/libsrc/osic1p/chline.s
new file mode 100644 (file)
index 0000000..be40d40
--- /dev/null
@@ -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 (file)
index 0000000..62342c2
--- /dev/null
@@ -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 (file)
index 0000000..fa901c1
--- /dev/null
@@ -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 (file)
index 0000000..84e5a45
--- /dev/null
@@ -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 (file)
index 0000000..40ed242
--- /dev/null
@@ -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 (file)
index 0000000..5e85e0b
--- /dev/null
@@ -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 (file)
index 0000000..b3bdaa0
--- /dev/null
@@ -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 (file)
index 0000000..0dea72b
--- /dev/null
@@ -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 (file)
index 0000000..f765373
--- /dev/null
@@ -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 (file)
index 0000000..693863d
--- /dev/null
@@ -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 (file)
index 0000000..b616b4a
--- /dev/null
@@ -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 (file)
index 0000000..073691a
--- /dev/null
@@ -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 (file)
index 0000000..eabeaf7
--- /dev/null
@@ -0,0 +1,4 @@
+; Addresses\r
+INPUTC          := $FD00        ; Input character from keyboard\r
+RESET           := $FF00        ; Reset address, show boot prompt\r
+KBD             := $DF00        ; Polled keyboard register\r
diff --git a/libsrc/osic1p/osiscreen.inc b/libsrc/osic1p/osiscreen.inc
new file mode 100644 (file)
index 0000000..66c5e9f
--- /dev/null
@@ -0,0 +1,184 @@
+;\r
+; Macro definitions for screen layout modules\r
+;\r
+\r
+        .include        "extzp.inc"\r
+        \r
+.linecont +\r
+\r
+;\r
+; Internal function for screensize()\r
+;\r
+.macro  osi_screensize ScrWidth, ScrHeight\r
+                                ; Macro implementation of internal screensize\r
+                                ; function for given width and height in\r
+                                ; characters\r
+                                \r
+        .export         screensize\r
+\r
+.proc   screensize\r
+        ldx     #ScrWidth\r
+        ldy     #ScrHeight\r
+        rts\r
+.endproc\r
+.endmacro\r
+\r
+;\r
+; void clrscr (void);\r
+;\r
+.macro  osi_clrscr ScrBase, ScrRamSize\r
+\r
+        .export         _clrscr\r
+\r
+.proc   _clrscr\r
+        lda     #<ScrBase       ; Fill whole video RAM with blanks by calling\r
+        ldx     #>ScrBase       ; memset appropriately\r
+        jsr     pushax\r
+        \r
+        lda     #' '\r
+        ldx     #$00\r
+        jsr     pushax\r
+        \r
+        lda     #<ScrRamSize\r
+        ldx     #>ScrRamSize\r
+        jsr     _memset\r
+\r
+        lda     #$00            ; Cursor in upper left corner\r
+        sta     CURS_X\r
+        sta     CURS_Y\r
+        \r
+        jmp     plot            ; Set the cursor position\r
+.endproc\r
+\r
+.endmacro\r
+\r
+;\r
+; cputc/cputcxy for Challenger 1P\r
+; Based on PET/CBM implementation\r
+;\r
+\r
+.macro  osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \\r
+                         ScrollDist, ScrLo, ScrHi\r
+\r
+                                ; Number of characters to move for scrolling\r
+                                ; by one line\r
+ScrollLength    = (ScrHeight - 1) * ScrollDist\r
+\r
+;\r
+; void cputcxy (unsigned char x, unsigned char y, char c);\r
+; void cputc (char c);\r
+;\r
+        .export         _cputcxy, _cputc, cputdirect, putchar\r
+        .export         newline, plot\r
+\r
+_cputcxy:\r
+        pha                     ; Save C\r
+        jsr     popa            ; Get Y\r
+        jsr     _gotoxy         ; Set cursor, drop x\r
+        pla                     ; Restore C\r
+\r
+; Plot a character - also used as internal function\r
+\r
+_cputc: cmp     #$0A            ; CR?\r
+        bne     L1\r
+        lda     #0\r
+        sta     CURS_X\r
+        beq     plot            ; Recalculate pointers\r
+\r
+L1:     cmp     #$0D            ; LF?\r
+        beq     newline         ; Recalculate pointers\r
+\r
+cputdirect:\r
+        jsr     putchar         ; Write the character to the screen\r
+\r
+; Advance cursor position, register Y contains horizontal position after\r
+; putchar\r
+\r
+        cpy     #(ScrWidth - 1) ; Check whether line is full\r
+        bne     L3\r
+        jsr     newline         ; New line\r
+        ldy     #$FF            ; + cr\r
+L3:     iny\r
+        sty     CURS_X\r
+        rts\r
+\r
+newline:\r
+        inc     CURS_Y\r
+        lda     CURS_Y\r
+        cmp     #ScrHeight      ; Screen height\r
+        bne     plot\r
+        dec     CURS_Y          ; Bottom of screen reached, scroll\r
+\r
+                                ; Scroll destination address\r
+        lda     #<(ScrBase + ScrFirstChar)\r
+        ldx     #>(ScrBase + ScrFirstChar)\r
+        jsr     pushax\r
+        \r
+                                ; Scroll source address\r
+        lda     #<(ScrBase + ScrFirstChar + ScrollDist)\r
+        ldx     #>(ScrBase + ScrFirstChar + ScrollDist)\r
+        jsr     pushax\r
+        \r
+                                ; Number of characters to move\r
+        lda     #<ScrollLength\r
+        ldx     #>ScrollLength\r
+        jsr     _memmove\r
+\r
+                                ; Address of first character in last line\r
+                                ; of screen\r
+        lda     #<(ScrBase + ScrFirstChar + ScrollLength)\r
+        sta     ptr1\r
+        lda     #>(ScrBase + ScrFirstChar + ScrollLength)\r
+        sta     ptr1+1\r
+        \r
+        ldy     #ScrWidth       ; Fill last line with blanks\r
+        lda     #' '\r
+clrln:  sta     (ptr1),y\r
+        dey\r
+        bpl     clrln\r
+\r
+plot:   ldy     CURS_Y\r
+        lda     ScrLo,y\r
+        sta     SCREEN_PTR\r
+        lda     ScrHi,y\r
+        sta     SCREEN_PTR+1\r
+        rts\r
+\r
+; Write one character to the screen without doing anything else, return X\r
+; position in register Y\r
+\r
+putchar:\r
+        ldy     CURS_X\r
+        sta     (SCREEN_PTR),y  ; Set char\r
+        rts\r
+        \r
+.endmacro\r
+\r
+.macro osi_screen_funcs ScrBase, ScrRamSize, ScrFirstChar, \\r
+                        ScrWidth, ScrHeight, ScrollDist\r
+\r
+        .import         popa, _gotoxy\r
+        .import         _memmove, _memset, pushax\r
+        .importzp       ptr1\r
+\r
+.rodata\r
+\r
+; Screen address tables - offset to real screen\r
+ScrTabLo:\r
+        .repeat ScrHeight, I\r
+        .byte <(ScrBase + ScrFirstChar + I * ScrollDist)\r
+        .endrep\r
+        \r
+ScrTabHi:\r
+        .repeat ScrHeight, I\r
+        .byte >(ScrBase + ScrFirstChar + I * ScrollDist)\r
+        .endrep\r
+\r
+.code\r
+\r
+osi_cputfuncs   ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \\r
+                         ScrollDist, ScrTabLo, ScrTabHi\r
+osi_screensize  ScrWidth, ScrHeight\r
+osi_clrscr      ScrBase, ScrRamSize\r
+\r
+.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 (file)
index 0000000..e691c2f
--- /dev/null
@@ -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 (file)
index 0000000..1155a8a
--- /dev/null
@@ -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 (file)
index 0000000..632cf4a
--- /dev/null
@@ -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 (file)
index 0000000..038622a
--- /dev/null
@@ -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 (file)
index 0000000..8bf8f16
--- /dev/null
@@ -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 (file)
index 0000000..261739d
--- /dev/null
@@ -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 (file)
index 0000000..e3f40bb
--- /dev/null
@@ -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 (file)
index 0000000..0ff991a
--- /dev/null
@@ -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 (file)
index 0000000..b2bb0f9
--- /dev/null
@@ -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 (file)
index 0000000..8d1cec8
--- /dev/null
@@ -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 (file)
index 0000000..e92e9ec
--- /dev/null
@@ -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 (file)
index 0000000..fa9a65c
--- /dev/null
@@ -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 (file)
index 0000000..abd74a5
--- /dev/null
@@ -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 (file)
index 0000000..dce9155
--- /dev/null
@@ -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 (file)
index 0000000..26dc589
--- /dev/null
@@ -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 (file)
index 0000000..fb61646
--- /dev/null
@@ -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 (file)
index 0000000..f34303d
--- /dev/null
@@ -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 (file)
index 0000000..746929d
--- /dev/null
@@ -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 (file)
index 0000000..2424c45
--- /dev/null
@@ -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 (file)
index 0000000..ba39740
--- /dev/null
@@ -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 (file)
index 0000000..e4426d0
--- /dev/null
@@ -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 (file)
index 0000000..e4afa7e
--- /dev/null
@@ -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 (file)
index 0000000..40f831e
--- /dev/null
@@ -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 (file)
index 0000000..4b80da2
--- /dev/null
@@ -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 (file)
index 0000000..45a78d5
--- /dev/null
@@ -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 (file)
index 0000000..b1d610f
--- /dev/null
@@ -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 (file)
index 0000000..17a7450
--- /dev/null
@@ -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 (file)
index 0000000..4e4d44d
--- /dev/null
@@ -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 (file)
index 0000000..af69c5e
--- /dev/null
@@ -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 (file)
index 0000000..878c793
--- /dev/null
@@ -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 (file)
index 0000000..9317d6c
--- /dev/null
@@ -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 (file)
index 0000000..b9f0f90
--- /dev/null
@@ -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
index 66aed0366f912dcf687849afbbae2116043e4492..c1c80530851adfc4fb73b937597903ee38a2a5e7 100644 (file)
@@ -94,7 +94,7 @@ L2:     lda     zpsave,x
 
 ; ------------------------------------------------------------------------
 
-.segment        "ZPSAVE"
+.segment        "INITBSS"
 
 zpsave: .res    zpspace
 
index 0d5b18987da51455e7455340fe896a2ba58abfcb..8ba6e31170393d15f40aacb433af4d082f349269 100644 (file)
@@ -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
index fc5f621af5b5c2f4ad91bd02578ac1823bece148..2c0fe722a49e40b8fc0cbf113ecfbd3c6439c5ab 100644 (file)
@@ -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
 
index b732459e0df17dfa18c80c7862a9fd05b035fd22..ae32975628ca067dc8db764a241ca6ac99a6285b 100644 (file)
@@ -195,7 +195,7 @@ spsave:         .res    1
 
 irqcount:       .byte   0
 
-.segment        "ZPSAVE"
+.segment        "INITBSS"
 
 zpsave:         .res    zpspace
 
index 7df8402fe1db13e7eefcdc07e134887be693b17e..59879978eb099e5c7add12f60a32945ce5ad93e3 100644 (file)
         .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
-
index 6c7b863533df3eb4e258deea80a33653ab4ede43..2a7f6a44b7c83728b44903798b2ab10416ed26de 100644 (file)
@@ -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
 
index 83cd7448273d1552cf34758627bf54cdebe2d905..0e6a84ebba275d6d001ab56d285a3dba857f9a6a 100644 (file)
@@ -31,9 +31,9 @@
 ;---------------------------------------------------------------------------
 ; Data
 
-.bss
-__argc:         .res    2
-__argv:         .res    2
+.data
+__argc:         .word   0
+__argv:         .addr   0
 
 
 
index 73df0991782ab65594b4a8d48de525aaf824385e..6186fe4e22c4f5eff1c0b0dab9c1fac86ad25f8c 100644 (file)
@@ -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 (file)
index e6c2422..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-;
-; Oliver Schmidt, 2013-05-16
-;
-; extern int errno;
-;
-
-        .include        "errno.inc"
-
-        .bss
-
-__errno:
-        .word   0
index e04881987cdc4a1fb70e91309682438dcc863677..6a0f94a03020756905b39b341f1640b4f7779969 100644 (file)
@@ -86,7 +86,7 @@ L2:     lda     zpsave,x
 
 ; ------------------------------------------------------------------------
 
-.segment        "ZPSAVE"
+.segment        "INITBSS"
 
 zpsave: .res    zpspace
 
index eda8f4f85749f79344ccea26ab4199568077e9ec..a41a1c4958ab1d58b0875e48d4c50acd3dd4a318 100644 (file)
         .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
-
index 8a1c4eee73764e78e88e3d97901656949e630cb6..69cf07bb317c5a703e30393968e8ed8542935929 100644 (file)
@@ -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
 
index 7810eb4f8a6b0c7b8b48763d6e53b081bb80397c..4e449a3ef7e3e3843b51d7e180c7760aacfb4182 100644 (file)
@@ -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;
index 79988ea7085fdff2f2118d652ba47251eafb755f..951706ce6a50c674e1f670b2ae8b7f5065886149 100644 (file)
@@ -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.?
index 5997fc8d04aba01d5c4608912586a187d232dc98..edd06ff02bd0c28a0223d4997b77154f4bd606ba 100644 (file)
@@ -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.
index 90a1d4bdcee00562653ab64d1085c11b400db85c..78c28af89ca6b1b705e70c60ae9361c58dd20910 100644 (file)
@@ -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;
 }
-
-
-
index 7d94096596018f69b1a1db5f19c447769355950c..4a849cb989b7c96395cfa11942446c5599c33909 100644 (file)
 
 
 
-#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.
index 9f110ec98c7ffa1b60c1a2fe47ab666286d40d59..8d0619888235d9c2e3549919b584474be4496501 100644 (file)
@@ -110,7 +110,7 @@ int main (void)
                     J = 0;
                 }
             }
-            if (kbhit() && ReadUpperKey == 'Q') {
+            if (kbhit() && ReadUpperKey () == 'Q') {
                 break;
             }
         }
index af176d019f0bcbf97e97f8d4f040fa57469c13eb..b3bb4cebea5791c78d9f4bacf010ffb8899a1be9 100644 (file)
@@ -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;
index e4d6f7363a7161121fb35449816cb2475c0dce28..ff4232c0050b42b8e0d0ed3a3bf0e49d3f1f2bab 100644 (file)
@@ -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;
index c398d2b377adc42665a2f81cf4148d54fdcc57d2..3462d5501c30848cf3d29d3f9c2cd45938c87fe5 100644 (file)
@@ -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;
     }
 
index 9682ad9b93314ee860beae01a31e8b31c046deb8..3a520a54a3e2ff5eee997eb6214035b7f41490e9 100644 (file)
@@ -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
index fbe163f5126da3fafd6d0a543c174fecbc31874e..ce4b15c034e352f0c8b536d5af368f9cc7dd84eb 100644 (file)
@@ -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);
index b3d6d6c6ed5190e91512e4dc08886e14bac9826f..e77b9201c36710b882e564532c9734a42ea09632 100644 (file)
@@ -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 */
+
index 378a776e651e7e9fd6af8d8e341b3c80706fb0ec..fb254f835342f13a07379c36ab0555395c4c66ec 100644 (file)
@@ -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 */
+
 
 
 
index 6acf8c94fdf74657d53eebc40dcebfef43218a2d..500db1985f429a669c2f2baa9256e49b90fa94d2 100644 (file)
@@ -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 },
index 634f2107ef32219b264df0064d29835965b4ecc7..1f6812ce03c5a29df32b52ec8a8cbc3c4cea2ac8 100644 (file)
@@ -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;
-        }
+            /* 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);
+            /* 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) {
+            /* Read tokens for one parameter, accept empty params */
+            Last = 0;
+            while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
+                TokNode* T;
 
-            TokNode* T;
+                /* Check for end of file */
+                if (CurTok.Tok == TOK_EOF) {
+                    Error ("Unexpected end of file");
+                    FreeMacExp (E);
+                    return;
+                }
 
-            /* 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 ();
 
-            /* 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;
 
-            /* Insert it into the list */
-            if (Last == 0) {
-                E->Params [E->ParamCount] = T;
-            } else {
-                Last->Next = T;
+                /* And skip it... */
+                NextTok ();
             }
-            Last = T;
 
-            /* And skip it... */
-            NextTok ();
-        }
+            /* One parameter more */
+            ++E->ParamCount;
 
-        /* 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 ();
+            }
 
-        /* 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 a comma */
+            if (CurTok.Tok == TOK_COMMA) {
+                NextTok ();
+            } else {
                 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);
index 3f31a2b88d203f2a0acb0422b139f3080c4bb5a8..d81a875778211560c3960f2179fdd4209197ac17 100644 (file)
@@ -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);
 
index 0b066c7bd9cc3b38ec1bae4f7b4d6f3493fe9d4b..4db780318c0c8f35a90aa8b95fb45910169eef6a 100644 (file)
@@ -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          },
index 890e1c7a33c264434a65337a12612a48bf0fc444..7993210669c713fb5af3e872de953fd13d6a0fb4 100644 (file)
@@ -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;
index f1459dca079e740f7f6df332cb021b4fb2c19af2..06c537cf694decd9309c41311f55852d13800d4e 100644 (file)
@@ -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 ());
 }
 
 
index 7e21dd30910d6b0de4712e203fd4c230aa706bc6..35d5a8066a220d514c29e4a7baca7eae525efb68 100644 (file)
@@ -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" : "---",
index 803b12785d304cd93b3fd1e896f545f3f6411f4a..bfc013a3ddc729f43dcd235e826194b451ca2534 100644 (file)
@@ -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,
index be80319e7389c79c2f5ea5dbcf76fff74bbf12f7..de51781a61c1af42fef0e06b4ec132e86c9aa7d4 100644 (file)
@@ -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;
index a4b99307372874f0cf7b83a7823f9ae54a78cc9c..92210ebb5504d5d4eff7a83dd6eea0afe8827aa4 100644 (file)
@@ -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)) {
-
-            CodeEntry* X;
-            unsigned J = 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) {
 
-            /* Generate the replacement sequence */
-            while (Count--) {
-                /* cmp #$80 */
-                X = NewCodeEntry (OP65_CMP, AM65_IMM, "$80", 0, E->LI);
-                CS_InsertEntry (S, X, J++);
+            if (L[3]->OPC == OP65_JSR                                           &&
+                SHIFT_TYPE (Shift = GetShift (L[3]->Arg)) == SHIFT_TYPE_ASR     &&
+                (Count2 = SHIFT_COUNT (Shift)) > 0) {
 
-                /* 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 */
index 0410652a1567a15dd5d4058d29dc1d9d1965bde4..e7f9cc359e28aaba84689346346cdce7eebde86b 100644 (file)
@@ -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);
index 427d0bd137e7fca39585e2e559c3f7f3c7c3507d..cf6392bd33a930a426f7d22b77c6e0d8fbc998dd 100644 (file)
@@ -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) {
index 053810b50c0b1356825700dc8bf216abd6fa92d6..8c9d6dcb00d6feb81cf12b7b2cc28316d7023c8f 100644 (file)
@@ -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;
     }
index 598d0a22859919f66fc33a624f92e93835a4b2f2..92b3d0122d3d71f475ddea95bf4d690f3a9d28ac 100644 (file)
@@ -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
index 693c2116e5c830ce836855089e7796ee336e517c..1630848350892bafc71df8006490d3720c8e35c9 100644 (file)
@@ -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)) {
-
-            /* 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;
+            /* 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;
+
+                /* 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;
             }
 
index 03374a52147f86d48edbe648b4935cff8e1e371d..34cf550a2e780b7e59b330297024930cd9d004e0 100644 (file)
@@ -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);
 }
index d9f1eeac320455234147aec92e9c75f0c375741e..22b305739cc09816531a15f26ee3e9db43566c32 100644 (file)
@@ -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 */
index e2800a65e45244c5b4176274206fa27bacb833ce..dbdd72f3c9bcd6d4ac26df9970eeb494efb6592b 100644 (file)
@@ -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 */
index 2abd786010289bae8c049bb6e0deacaa81c2af1d..8b0af5a83729355f2e9520d4368f1d8a4cc734d2 100644 (file)
@@ -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 */
index 34688e97ebc325a739ccc1e86627236988c8b7a2..1041b8fa2df57d33019dd5b88ed2e5fb7eb432b5 100644 (file)
@@ -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             },
index a5ab4897eaeffc236cf713ebb5e41816ea82c069..99ce6acc13934369fe9d352a612cf42c10c27751 100644 (file)
@@ -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.
     */
index aa5949f9797f7c5f185776ef47ba0eb098909254..980ee27f2dab87e2c62fcf7f847a7ec5f12e842b 100644 (file)
@@ -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");
 
index 1f63e9430da997d511994f76b0bd3933ed5f514a..fdf45987370581f3d833104d92f937c4080b7d70 100644 (file)
@@ -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;
 
index 67941026bc8ee24fe6b2890154b86ef12d29256a..673dfa163b97e19792097e4e9f77cb2a29604978 100644 (file)
@@ -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;
index a0a6ed02b5ad88f06a50b5b3e2983a5a24cb5226..4268a569bcff7cdc984cf8424b9d6855017978b9 100644 (file)
@@ -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"
index 5d1b60ea3ab0cae6da16d86d0c88e50d2d3f7d98..ce13ae132f34b167e16801d7322a0ecbd77ad3cd 100644 (file)
@@ -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
 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;
index fc5125c340529e5ba8a869e02b41055d598f0acb..283285c76e50c667154f0d7b2810c87d96774e30 100644 (file)
@@ -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
 
 
 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);
 }
index 716df1efb3331fb00f4369ad7a0f14050905934d..0f6622934beabc03d002bad0ce35cdac7cc4663a 100644 (file)
@@ -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;
 }
 
index b18906c7a1b01d65ce093533d05edd5987c314e6..1caf0cfb64dbe651af68f652c959bdd7a8a0d4ca 100644 (file)
@@ -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.
index ffb342e2553fa9e637f6696a72445e54b45ce5a4..60b9af6603c1f75d4d3751c6d2c6c8e08169f532 100644 (file)
@@ -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 */
index 72dffe38220bf5120aed779772b653e00c8ad166..3ea562aa6dc9c4d26761ad13533b40c5b22ab31f 100644 (file)
@@ -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;
 
index d2fcf4f409379745b0feacf27efbb42a54520d58..4e61a5f8388b5d9704fdc331c0a5f5af2464b57a 100644 (file)
@@ -47,7 +47,7 @@
 
 
 #define VER_MAJOR       2U
-#define VER_MINOR       14U
+#define VER_MINOR       15U
 
 
 
index 1cfb5ba455b8ccdac391a1c17770b199feebb64d..a9143584ab81a3a010db6af72d5732ed3c9d8c3b 100644 (file)
@@ -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 */
 {
index c9fb9c35fde0f98a18234914c7ba6e1a761da175..18515ce495013901aa9aa2878cd6de32a431b1a1 100644 (file)
@@ -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       */
 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
index f4c37818fa94ef85d5265af1d706f25d39048ad8..7355e60d17c75ba01549372bfb35c15b543f930b 100644 (file)
@@ -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;
index 4ee1ffd79c5de7f2aa51ff9cd1943c39d21ddffd..e8ce66cf7b52a91e602c4b8d1d8226f7e3066819 100644 (file)
@@ -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 */
index a819f977194bcf36fcf400c8b027492370d068a8..8c37e1ae2d3ae1864c3dba1d45515557d7201b02 100644 (file)
@@ -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;
+        }
     }
 }
 
index 9098d7d3766c55c8b3464fe665fbcaa7a5b0c9ce..4daacb1ee5222f813dc6f6f82f27d3f7af2d1c0c 100644 (file)
@@ -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 */
 {
index ad5f8d34e29a0fd5444578fdb6610c77816b52fd..13ea0cc859645e0c8cfc53d1b13a10d015c9be32 100644 (file)
@@ -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
index cad2096ff9ede24825da369f6bd6bb4bffe8ebde..12d4cf65699dc428f408d11838d6b6540b2c58e7 100644 (file)
@@ -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       */
 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;
+}
index 14700ba99f8258ee31c7e7103822f796247709f0..b1423bb41a3bcfa5ed43e135dc188fe4949bdad7 100644 (file)
@@ -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       */
 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 */
 
+/* End of segment.h */
 #endif
index 41200e86a0f5082b3164f3b91fc32375a821af99..ba5d83849754ffeb36e1a4be69f8f280a5a95d81 100644 (file)
@@ -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 */
index 46e9a48fbd4923ef42f705d2738b021a7b3ad806..8e7a049c7df5fa57abbd59fb6c8752480e683580 100644 (file)
@@ -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);
index 5030b1dc38839d015eac430a1e23a0af8cadfcea..95ed143966cc15d7974e7045170ed276813edf32 100644 (file)
@@ -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 */
index 22f6831e4fe7a7987b0bdcaa37e57b6ba338f9f4..dab9b0be8dda94255bd9b63aefd1c2420079c094 100644 (file)
@@ -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 */
         }
     }
index 0deb59a5fdfb98eb64932f85fa2e95e42a9f3158..56211b5c17558d57e56d3132cd7b9f2c483ffb8d 100644 (file)
@@ -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) {
index b942cbcdf0f555a260f3779e42a6bad4c49ced16..1ad86ca98d25d8a8bbabbd00f5b321c67e76c275 100644 (file)
@@ -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): bdiff.c | $(WORKDIR)
+       $(CC) -O2 -o $@ $<
 
-$(WORKDIR)/bdiff$(EXE): $(WORKDIR)
-       @$(CC) -o $(WORKDIR)/bdiff$(EXE) bdiff.c
+.NOTPARALLEL:
 
-dotests: $(WORKDIR)/bdiff$(EXE)
-       @$(MAKE) -C val clean all
-       @$(MAKE) -C ref clean all
-       @$(MAKE) -C err clean all
-       @$(MAKE) -C misc clean all
+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))
index 40ccfcb593bda6bc64141054c8d978deae728246..bc4226acbf04a7564ea81612dedef92e20924b3b 100644 (file)
@@ -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))
index 265df0aaca3e8db52554ce0dd51aa71c8f107399..65ce6ec83abf8e0abe4bbdb47519ea5590522c91 100644 (file)
@@ -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 (file)
index 0000000..c4a836e
--- /dev/null
@@ -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 (file)
index 0000000..14e14d4
--- /dev/null
@@ -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 (file)
index 0000000..ffc8c9a
--- /dev/null
@@ -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 (file)
index 0000000..34c862a
--- /dev/null
@@ -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 (file)
index 0000000..2bf8267
--- /dev/null
@@ -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 (file)
index 0000000..0a7f44e
--- /dev/null
@@ -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 (file)
index 0000000..41229ad
--- /dev/null
@@ -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 (file)
index 0000000..a08ab11
--- /dev/null
@@ -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 (file)
index 0000000..71e6368
--- /dev/null
@@ -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 (file)
index 0000000..d18dc0b
--- /dev/null
@@ -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 (file)
index 0000000..8cf805b
--- /dev/null
@@ -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 (file)
index 0000000..c890978
--- /dev/null
@@ -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 (file)
index 0000000..5b6839a
--- /dev/null
@@ -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 (file)
index 0000000..a2cdeb7
--- /dev/null
@@ -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;
+}
index b18d9165eea916f7fea5d95bcabccbce18e0dc1a..918316c6c852daf1614f2a66be71bd7d7581dc66 100644 (file)
@@ -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 (executable)
index 0000000..26cef70
--- /dev/null
@@ -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;
+}
index b752adc1dec1717e6e2a4552277308ec8e0d341b..09dd96d4425455f290c50a165751835c50d64576 100644 (file)
@@ -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))
index f3d6c71ec542c128c9ecec3a504d4ec35d0e9c86..aa5df158f22e1e77c62fc7a8f01085b46eb28261 100644 (file)
@@ -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;
index 2e0aca2781bd48b64555a61d2672419410587789..4ad8160efbb2080a183229445dd790cc3bb814f8 100644 (file)
@@ -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
-
-CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
-SIM65 := $(if $(wildcard ../../bin/sim65*),../../bin/sim65,sim65)
-
 ifdef CMD_EXE
-RM := del /f
+  DEL = -del /f $(subst /,\,$1)
 else
-RM := rm -f
+  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*),../../bin/sim65,sim65)
+
+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 (executable)
index 0000000..4ca32d0
--- /dev/null
@@ -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 (file)
index 0000000..f8b7d66
--- /dev/null
@@ -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 (executable)
index 0000000..d492f6b
--- /dev/null
@@ -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 (executable)
index 0000000..ae5cd3d
--- /dev/null
@@ -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 (executable)
index 0000000..1d7792c
--- /dev/null
@@ -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 (file)
index 0000000..cd644f4
--- /dev/null
@@ -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 (file)
index 0000000..3390ac9
--- /dev/null
@@ -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;
+}
index e1682507ae80c39fcb27244dd8b0e2c120cb8085..55503e176d1ebe11177d27ab4536b93ff3d82779 100644 (file)
@@ -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 (file)
index 0000000..0cd691c
--- /dev/null
@@ -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 (file)
index 0000000..ae2ba62
--- /dev/null
@@ -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 (file)
index 0000000..4e9190d
--- /dev/null
@@ -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 (file)
index 0000000..9bb8eaa
--- /dev/null
@@ -0,0 +1,2 @@
+*.o
+em-test-*
diff --git a/testcode/lib/conio.c b/testcode/lib/conio.c
new file mode 100644 (file)
index 0000000..bdee122
--- /dev/null
@@ -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;
+        }
+}
index bd4eddc6a9a29fec089c27853ef6f533adfd7e3a..f4a56029a2b13184f28933be4db5a2f9bcaf86e4 100644 (file)
@@ -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 ();
+    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 (DRIVERNAME);
+    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 (file)
index 0000000..9a4dd75
--- /dev/null
@@ -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 (file)
index 0000000..a4bd63b
--- /dev/null
@@ -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 (file)
index 0000000..d3af47d
--- /dev/null
@@ -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;
+}